C#——协变逆变

简介: C#——协变逆变

用官方的话来讲:协变和逆变都是术语,前者指能够使用比原始指定的派生类型的派生程度更大(更具体的)的类型,后者指能够使用比原始指定的派生类型的派生程度更小(不太具体的)的类型。

协变:即和谐的变化,自然的变化。因为里氏替换原则父类可以装子类所以子类变父类,比如string变成object感受是和谐的。

逆变:即逆常规的变化,不正常的变化。因为里氏替换原则父类可以装子类但是子类不能装父类所以父类变子类,比如object变成string感受是不和谐的。

协变和逆变的公式为:

协变:IFoo<父类> = IFoo<[子类]
逆变:IBar<子类> = IBar<父类>;

举个例子

协变:

using System;
using System.Collections.Generic;
class MainClass
{
    static void Main()
    {
        IEnumerable<object> list = new List<string>();
    }
}

逆变:

using System;
class MainClass
{
    static void Main()
    {
        Action<string> action = new Action<object>((o)=> { });
        action("");
    }
}

协变和逆变是用来修饰泛型的协变:out;逆变:in。在泛型中out修饰泛型称为协变,协变(covariant)  修饰返回值 ,协变的原理是把子类指向父类的关系,拿到泛型中;在泛型中in 修饰泛型称为逆变, 逆变(contravariant )修饰传入参数,逆变的原理是把父类指向子类的关系,拿到泛型中。用于在泛型中修饰泛型字母的,只有泛型接口和泛型委托能使用。

那么协变和逆变的作用是什么呢?

为了防止开发者写出错误的代码,.net 设计者便用了协变和逆变(对应 out 和 in 关键字)来强制要求正确行为。也就是说,即使我们想这么做,一旦我们用了微软提供的 IEnumerable 等接口,我们也无法进行错误的类型转换了。所以归根到底,协变和逆变只是一种约束而已,这种规范限制了我们的泛型接口中要么只能有将类型参数当作返回值的协变相容方法(加了 out 关键字),要么只能有将类型参数当作输入值的逆变相容方法(加了 in 关键字)。

目录
相关文章
|
6月前
|
安全 C#
C#进阶-协变与逆变
我们知道子类转换到父类,在C#中是能够隐式转换的。这种子类到父类的转换就是协变。而另外一种类似于父类转向子类的变换,可以简单的理解为逆变。逆变协变可以用于泛型委托和泛型接口,本篇文章我们将讲解C#里逆变和协变的使用。逆变和协变的语法第一次接触难免感到陌生,最好的学习方式就是在项目中多去使用,相信会有很多感悟。
66 0
|
编译器 C#
C#中的协变和逆变
C#中的协变和逆变
116 0
|
算法
一起谈.NET技术,C#4.0新特性-&quot;协变&quot;与&quot;逆变&quot;以及背后的编程思想
  在《上篇》中我们揭示了“缺省参数”的本质,现在我们接着来谈谈C#4.0中另一个重要的新特性:协变(Covariance)与逆变(Contravariance)。对于协变与逆变,大家肯定不会感到陌生,但是我相信有很多人不能很清晰地说出他们之间的区别。
906 0
|
算法
C#4.0新特性-&quot;协变&quot;“.NET研究”与&quot;逆变&quot;以及背后的编程思想
  在《上篇》中我们揭示了“缺省参数”的本质,现在我们接着来谈谈C#4.0中另一个重要的新特性:协变(Covariance)与逆变(Contravariance)。对于协变与逆变,大家肯定不会感到陌生,但是我相信有很多人不能很清晰地说出他们之间的区别。
1094 0
|
C# 编译器 Java
C# 逆变与协变
原文:C# 逆变与协变 该文章中使用了较多的 委托delegate和Lambda表达式,如果你并不熟悉这些,请查看我的文章《委托与匿名委托》、《匿名委托与Lambda表达式》以便帮你建立完整的知识体系。
1350 0