【问题标题】:What are the benefits of covariance and contravariance?协变和逆变有什么好处?
【发布时间】:2010-10-22 15:00:42
【问题描述】:

C# 4.0 将支持协变和逆变。但我并不清楚这个新功能的好处。你能解释一下(清楚地)我们为什么需要它吗?

【问题讨论】:

  • Bart De Smet 有一篇很棒的关于协变和逆变的博客文章 here

标签: c# covariance contravariance


【解决方案1】:

在我看来,协方差将有很大帮助的好处之一是 Generics

我遇到了几种情况,需要显式使用Cast 将特定类型转换到它的基类。

class Foo { }
class Bar : Foo { }

// ...

IEnumerable<Foo> foos = new List<Foo>();
IEnumerable<Bar> bars = new List<Bar>();

foos = bars.Cast<Foo>();

// C# 4.0
foos = bars;

这里有一个关于这个主题的good reference

【讨论】:

  • 不过,过度使用斜体还是不错的选择。
  • 对不起 :( 忘记类定义
【解决方案2】:

对于 4.0 中的工作方式和内容存在很多误解。到目前为止,我读过的最好的解释是我的 Marc Gravell 写的。在此处查看他的博客文章:

http://marcgravell.blogspot.com/2009/02/what-c-40-covariance-doesn-do.html

重申一下,很多人认为这将在 4.0 中起作用:

public class Base{}
public class Derived : Base {}

..在其他类中

List<Derived> derived....

public void Method(List<Base> b){}

即使在 4.0 中,您也无法将 List 传递给此方法。正如 Marc 指出的那样,这就是通用约束的用途,并且可以从 2.0 开始实现

【讨论】:

  • 这对我来说似乎很奇怪。您不能通过 List 的唯一原因是 List 是可变的;当然你不能这样通过,因为添加项目会破坏它的类型限制。
  • @mquander:奇怪的不合逻辑? API (pre 4.0) 没有什么可说的,“只有当对象是不可变的,你才能做这个操作”。
  • 我的意思是 List 允许您添加和更改 Ts 的事实就是它没有意义的原因。如果您尝试在 IList 上添加“out”参数以允许这样做,那么这些方法将无法再按预期工作。
【解决方案3】:

有一篇很好的文章讨论了这个问题here

【讨论】:

    【解决方案4】:

    它们只是允许您做一些在概念上有效且形式上可接受的事情,但由于语言限制目前不允许。例如:

    IEnumerable<int> ints = new List<int> { 1, 2, 3 };
    
    Action<IEnumerable<object>> PrintThings =
        x => { foreach(var thing in x) Console.WriteLine(thing); };
    
    PrintThings(ints); // doesn't compile right now :(  will compile in 4.0
    

    这不能或不应该工作没有根本原因;它只是碰巧在语言中是不允许的。通过允许它,您可以让程序员的生活更轻松,因为这样的操作对他们来说是很自然的。

    【讨论】:

    • 上述在 4.0 之前不起作用的根本原因是语法中没有办法在不失去类型安全的情况下允许它。如果您允许它用于您的示例,那么您也必须允许它用于不保留类型安全的示例。
    • 没错,这就是为什么他们要添加新的“in”和“out”关键字来支持它(并且 IEnumerable 将是 以允许这种情况。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 2010-11-12
    • 2016-11-03
    • 2015-02-09
    • 2012-04-06
    • 1970-01-01
    相关资源
    最近更新 更多