在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>
{}
我不明白为什么这是必要的?
答案 0 :(得分:7)
因为否则它不是可用的类型,因为CLR仍然不知道T
使用哪种类型。
List<T>
是打开类型,因为T
尚未替换为可实例化的类型。而且您无法创建开放类型的实例。您只能在关闭时创建类型的实例,即当所有类型参数(包括封闭类型和基类型)已被可实例化类型替换时。
如果您能够声明class MyTList : MyList<T> { }
,那么您永远无法为T
指定类型,因为MyTList
不再包含该类型参数,因此你永远无法实例化MyTList
。这不是一个非常有用的课程。
答案 1 :(得分:5)
如果您没有指定类型,那么唯一的另一个选择是使派生类也是通用的。
public class MyDerivedList<T> : MyList<T>
{
}
答案 2 :(得分:4)
嗯,非泛型类没有类型参数,泛型类有一个或多个类型参数。
如果从泛型类继承该类,而未指定type参数,则仍然具有泛型类,即
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中的类可以具有零或更多的arity,这意味着它们可以指定零个或多个类型参数。但是,CLR无法实例化具有非零arity的类,因此为了做任何有用的事情,必须将类的arity降低到零。
这意味着,虽然我们可以部分指定类:
public class IntKeyDictionary<TValue> : Dictionary<int, TValue>
减少arity,甚至声明像
这样的类public class ListAndAHalf<TOne, TTwo> : List<TOne>
增加了arity,故事必须以一个arity为0的类结束,如List<string>
,Dictionary<int, double>
等......
答案 3 :(得分:2)
如果不是怎么办?
您的MyStringList
将是通用的(因为T
没有硬编码类型),但是根据定义,它不是构建非泛型类。
答案 4 :(得分:2)
反过来想想它。如果您没有为基本类型指定type参数,那么 MyList<T>
应该使用哪种类型?它仍然是未定义的。
您可以创建一个继承自另一个泛型类型的泛型类型,然后您不必指定超类型的类型参数;你的客户可以做到。