C# 的协变和逆变

发布日期:2026-07-14 02:19:03   来源 : 杭州电子商务研究院    浏览量 :14
杭州电子商务研究院 发布日期:2026-07-14 02:19:03  
14

介绍

随着 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 版引入了两个新关键字:inout。它们指的是可以放置在特定位置的参数类型。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# 语言的原因在于,您可以使用多态特性扩展数组、委托类型和泛型类型。根据您处理的数据类型选择同变或逆变。

以上内容来自杭州电子商务研究院推送
关注
关于我们
热门推荐
合作伙伴
免责声明:本站部分资讯来源于网络,如有侵权请及时联系客服,我们将尽快处理
Copyright © 2025-2027 ToB产业网址导航 公安备案 浙公网安备33010602013138号 浙ICP备16025413号-9
支持 反馈 关注 数据