为什么C#4.0中的类没有通用方差?

时间:2010-04-28 21:44:45

标签: c# .net generics c#-4.0

如果我们有接口,为什么我们也没有它用于类?使用它时会产生什么问题?

3 个答案:

答案 0 :(得分:106)

假设你有一个在T中具有协变性的类C<T>。它的实现是什么样的? T必须出来。这意味着C<T>不能有任何方法接受T,任何类型为T的属性,带有setter,或任何类型为T 的字段,因为字段在逻辑上与属性setter相同; T进去了。

就T而言,使用协变类构建的唯一有用的东西是不可变的。现在,我认为拥有协变不可变列表和堆栈以及类型类型将是非常棒的。但是这个特征并不是那么明显,以至于它可以明确证明在使类型系统本身支持协变不可变类类型方面的大量开支是合理的。

上面的评论询问了一个有用的例子。请考虑以下草图:

sealed class Stack<out T>
{
    private readonly T head;
    private readonly Stack<T> tail;
    public T Peek() { return head; }
    public Stack<T> Pop() { return tail; }
    public Stack(T head, Stack<T> tail)
    {
        this.tail = tail;
        this.head = head;
    }
}
static class StackExtensions
{
    public static Stack<T> Push<T>(this Stack<T> tail, T head) 
    {
        return new Stack<T>(head, tail);
    }
    public static bool IsEmpty<T>(this Stack<T> stack)
    {
        return stack == null;
    }
}

假设您有协变类。现在你可以说

Stack<string> strings = null;
strings = strings.Push("hello");
strings = strings.Push("goodbye");
Stack<object> objects = strings;
objects = objects.Push(123);

嘿,我们只是把一个整数推到一堆字符串上,但一切都很好!没有理由为什么这不是类型安全的。在可变数据结构上违反类型安全的操作可以在不可变数据结构上安全地协变。

答案 1 :(得分:2)

答案 2 :(得分:2)

.NET团队以及C#和VB.NET团队的资源有限,他们在共同和逆变上所做的工作解决了大部分现实问题。类型系统非常复杂 - 如果在其他情况下导致不安全的代码,那么在99.9999%的情况下工作的解决方案就不够好。

我不认为在类方法上支持共同和逆变规范(例如“in”/“out”)的成本/时间具有足够大的价值。我可以看到极少数情况下它们是可用的 - 由于缺少乘法类继承。

您是否宁愿等待另外6个月的.net以获得此支持?


另一种想到这一点的方法是.net

  • 接口 / delegates - 用于为应用程序的概念类型系统建模
  • 用于实施上述类型
  • 类继承用于在执行上述操作时减少代码重复
  • 合作和逆转是关于应用的概念类型系统