3

在 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>
{}

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

4

5 回答 5

7

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

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

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

于 2013-01-29T13:47:52.660 回答
5

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

public class MyDerivedList<T> : MyList<T>
{
}
于 2013-01-29T13:48:17.510 回答
4

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

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

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>

减少了arity,甚至声明了类似的类

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

增加arity,故事必须以arity为0的类结束,比如List<string>Dictionary<int, double>等等......

于 2013-01-29T13:47:42.270 回答
2

如果不是呢?

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

于 2013-01-29T13:48:58.303 回答
2

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

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

于 2013-01-29T13:49:48.760 回答