代码之家  ›  专栏  ›  技术社区  ›  bitbonk

为什么泛型类型参数的.NET 4方差也不适用于类?[复制品]

  •  3
  • bitbonk  · 技术社区  · 15 年前

    可能重复:
    Why isn't there generic variance for classes in C# 4.0?
    Why does C# (4.0) not allow co- and contravariance in generic class types?

    新的.NET 4.0通用类型参数的协变和逆变只适用于接口和委托。为什么不为类支持它呢?

    2 回复  |  直到 15 年前
        1
  •  8
  •   Joe Albahari    15 年前

    对于类型安全,C 4.0仅支持标记为 在里面 外面的 .

    如果扩展到类,您还必须用in-out标记类型参数,这将导致非常严格的限制。这很可能就是为什么clr的设计者不允许这样做的原因。例如,考虑以下类:

    public class Stack<T>
    {
      int position;
      T[] data = new T[100];
      public void Push (T obj)   { data[position++] = obj;  }
      public T Pop()             { return data[--position]; }
    }
    

    我们不可能将t注释为out,因为t同时用于输入和输出位置。因此,即使在C支持的类的协变/逆变类型参数中,此类也永远不能协变或逆变。

    接口很好地解决了这个问题。我们可以定义如下两个接口,并让堆栈实现这两个接口:

    public interface IPoppable<out T> { T Pop(); }
    public interface IPushable<in T> { void Push (T obj); }
    

    注意,t是协变的,对于可ipOppable是协变的,对于可ipushable是反变的。这意味着t可以是协变的,也可以是反变的——这取决于您是强制转换为可ipOppable还是可ipushable。

    协方差/反方差在类中使用有限的另一个原因是它将排除使用类型参数作为字段的可能性——因为字段有效地允许输入和输出操作。事实上,编写一个用类型参数标记为In或Out的类是很困难的。即使是编写协变可枚举实现的最简单的情况也会带来一个挑战——您将如何从一开始就将源数据放入实例中?

        2
  •  1
  •   Ian Ringrose    15 年前

    .NET团队以及C_和VB.NET团队的资源有限,他们在协变和逆变方面所做的工作也有限。 解决了大多数现实世界的问题 . 类型系统非常复杂,很难正确理解。如果在其他情况下导致不安全代码,99.9999%的情况下可用的解决方案就不够好。

    我不认为在类方法上支持协变和逆变规范(例如in/out)的成本/时间具有足够的价值。我可以看到很少的情况下,由于缺乏多类继承,它们可以被使用。

    你宁愿再等6个月才能得到.NET的支持吗?


    另一种思考方法是在.NET中

    • 界面 /代表“被用来模拟 概念型系统 应用程序的
    • 等级 习惯于 实施 以上类型
    • 类继承 用于在执行上述操作时减少代码重复
    • 协变与逆变 是关于 概念型系统 应用程序的
    推荐文章