【问题标题】:why a non generic derived type must specify the type parameter for a generic base class C#为什么非泛型派生类型必须为泛型基类 C# 指定类型参数
【发布时间】:2013-01-29 13:45:45
【问题描述】:

在 Andrew Tolson 的 Pro C# 中,作者说当非泛型类扩展泛型基类时,派生类必须指定类型参数。

// Assume you have created a custom
// generic list class.
public class MyList<T>
{
  private List<T> listOfData = new List<T>();
}
// Non-generic classes must specify the type
// parameter when deriving from a
// generic base class.
public class MyStringList : MyList<string>
{}

我不明白为什么这是必要的?

【问题讨论】:

  • 如果没有在派生类中明确指定类型参数,编译器应该如何猜测T的类型是什么?
  • 您会提出什么替代方案?

标签: c# .net generics


【解决方案1】:

因为否则它不是可用的类型,因为 CLR 仍然不知道要为 T 使用哪种类型。

List&lt;T&gt;open 类型,因为 T 尚未被可实例化类型替换。而且您不能创建开放类型的实例。您只能在类型关闭时创建一个类型的实例,即当它的所有类型参数(包括封闭类型和基类型)都已被可实例化类型替换时。

如果您能够声明class MyTList : MyList&lt;T&gt; { },那么您将永远无法为T 指定类型,因为MyTList 不再包含该类型参数,因此您永远无法实例化@987654327 @。那不会是一个非常有用的课程。

【讨论】:

    【解决方案2】:

    如果您不指定类型,那么唯一的其他选择就是将派生类也设为泛型。

    public class MyDerivedList<T> : MyList<T>
    {
    }
    

    【讨论】:

      【解决方案3】:

      嗯,非泛型类没有类型参数,而泛型类有一个或多个类型参数。

      如果你从泛型类继承类,没有指定类型参数,你仍然有一个泛型类,即

      public class MyList<T> : List<T> {} //MyList is still generic
      

      但是

      public class MyList : List<T> {} //invalid declaration, what is T ?
      

      所以

      public class MyStringList : List<string> {} //specified with string
      

      或者,更一般的

      public class MyArrayList : List<object> {} //specified with object
      

      更冗长的解释,主要是因为我喜欢使用“arity”这个词。

      CLR 中的类可以有零个或多个,这意味着它们可以指定零个或多个类型参数。但是,CLR 无法实例化具有非零元数的类,因此为了做任何有用的事情,必须将类的元数降为零。

      这意味着,虽然我们可以部分指定类,例如:

      public class IntKeyDictionary<TValue> : Dictionary<int, TValue>
      

      减少数量,甚至声明类

      public class ListAndAHalf<TOne, TTwo> : List<TOne>
      

      增加arity,故事必须以arity为0的类结束,例如List&lt;string&gt;Dictionary&lt;int, double&gt;等...

      【讨论】:

        【解决方案4】:

        如果不是呢?

        您的MyStringList 将是泛型的(因为T 不会有硬编码类型),但它不是根据定义,因为您构建了一个非泛型类。

        【讨论】:

          【解决方案5】:

          反过来想。如果你没有为你的基本类型指定类型参数,MyList&lt;T&gt; 应该使用什么类型应该?它仍然是未定义的。

          您可以创建一个从另一个泛型类型继承的泛型类型,然后您不必指定超类型的类型参数;您的客户可以做到。

          【讨论】:

          • 您仍然需要指定基类的类型参数,但您可以根据自己的类型参数来指定。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-10-09
          • 2014-03-22
          • 2012-09-08
          • 1970-01-01
          • 2013-10-26
          • 2012-10-31
          • 1970-01-01
          相关资源
          最近更新 更多