c#

位置:IT落伍者 >> c# >> 浏览文章

理解.NET泛型中的协变与逆变


发布日期:2023年03月26日
 
理解.NET泛型中的协变与逆变

当前NET语言如VB和C#还不支持泛型的协变(covariance)与逆变(contravariance)尽管微软中的很多人也在谈论它但是在不远的将来这还是不太可能出现对协变与逆变的完整介绍要花很长时间基于此请大家参考Eric Lippert的关于C#中的协变与逆变的系列文章为了在VB中增加协变与逆变的泛型支持Lucian Wischik提出了下面的语法

类型参数可由关键字InOut修饰In类型只能作为方法参数与此类似Out类型只能作为方法的返回类型

使用Out类型的一个例子就是IEnumerable(Of T)如果某函数接受一个IEnumerable(Of Animal)类型参数那么我们就可以给它传一个IEnumerable(of Bird)对于In类型一个不太恰当的例子就是顺序看一下下面的接口Interface IWriter(Of T) Write(value As T)

如果你向接受Writer(Of Animal)类型参数的函数传一个IWriter(Of Bird)当然就不对了该方法可以将Animal的任何子类传给IWriterWrite但是它只接受Birds如果使用注解该接口看起来像下面这样Interface IEnumerable(Of Out T)Interface IWriter(Of In T)

这是针对VB编写的它也可以用在C#上

interface IEnumerableinterface IWriter不幸的是这种语法并不能直接应用在大多数常见的场景中比如IList(Of T)当传给一个向集合中写入的方法时T应该是In类型但是当传给一个从集合中读取的方法时T应该是Out类型或许这里应该针对IList创建一个基类该类会将接受T与返回T的方法区分开来

追溯过去C#和VB都支持数组协变(out/IEnumerable情况)尽管在逆变的情况下这会导致运行时错误(in/IWriter情况)这样做的目的是使C#更兼容于Java大多数人都认为这是一个不好的设计但是现在却无法改变了

上一篇:.net 2.0中iframe并且控制滚动条的方法

下一篇:c#中构建异常处理