C# 的协变和逆变
介绍
随着 C# 4.0 版的推出,该语言提供的用于解决不同问题的工具集已经非常丰富,现在又添加了两个新功能。这两个功能是协变和逆变。本指南将阐明这些术语,并在实际代码中向您展示它们如何丰富功能集并允许开发人员为以前需要变通方法的问题提供解决方案。
协变和逆变指的是你如何处理一个对象。当你只允许将元素推入类型为T或其子类型的元素时,列表等不可变集合类就是协变的。当你使用可变集合时,协变就会出现。
方差作为一个术语,表示作用于特定类型和运算符顺序的运算符的属性。前缀co表示“一起”,并告知您该运算符与其操作数相比时保留了类型的顺序。前缀contra表示“反对”某物,并告知您该运算符与其操作数相比时反转了类型的顺序。
方差:一致或相反
以下问题与服务器和网络设备有关。假设您有一个具有名称和状态的设备列表。制作列表时,请包括您要处理的设备,并确保这些设备具有唯一的名称和状态。
以下是协方差的演示:
List<Devices> switches = GetSwitches();
使用 C# 3.0,此代码无法编译,因为编译器无法确定您拥有 switch 集合后可以做什么或不能做什么。没有什么可以阻止您将服务器添加到集合中,这意味着不能保证不会发生以下情况。
switches.Add(new Server("Domain Controller","up"));
编译器拒绝编译该代码。这表明了逆变。
在以下示例中,即使该方法返回List< Devices > ,编译器也会允许该代码。这是因为所有交换机都是设备。
List<Switch> switches = GetAccess();
switches.Add(new Switch("DC-CORE-1","up"));
我们可以改变类型。
List<Devices> switches = GetAccess();
switches.Add(new Switch("DC-CORE-1","up"));
然而,这也是模棱两可的,因为你的意思也可能是以下内容:
List<Switch> switches = GetAccess();
Switch dccore = switches[0];
4.0 版引入了两个新关键字:in和out。它们指的是可以放置在特定位置的参数类型。in标记输入位置,out标记输出位置。
这使我们能够编码我们的初衷。
IEnumerable<Devices> devices = GetSwitches();
List 既有出方向,也有入方向,也就是说它既不是同变的也不是逆变的。以下是例子:
interface IOnlyDevices<in T>{
void Add(T value);
}
简单的界面可以执行以下操作:
IOnlyDevices<Switch> switches = GetAccess();
switches.Add(new Switch("DC-CORE-1","up"));
因此现在最后一条语句是安全且明确的。
结论
逆变允许您使用派生程度低于最初指定的类型,而协变允许您使用派生程度更高的类型。从某种意义上说,它们被引入 C# 语言的原因在于,您可以使用多态特性扩展数组、委托类型和泛型类型。根据您处理的数据类型选择同变或逆变。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~