多个类型参数
泛型可以使用任意多个参数类型。上面的 Stack 示例中只使用了一种类型。假设您创建了一个存储值和键的简单 Dictionary 类。在程序中可以通过声明两个参数(放在类定义的尖括号中并用逗号分隔)来定义一个泛型版本的 Dictionary 类:
public class Dictionary
{
public void Add(KeyType key, ValType val)
{
...
}
public ValType this[KeyType key]
{
...
}
}
使用该 Dictionary 类时,需要在实例化语句的尖括号中提供多个以逗号分隔的参数,并为 Add 函数和索引生成器提供正确类型的参数:
Dictionary dict = new Dictionary();
dict.Add(3, new Customer());
Customer c = dict.Get[3];
约束
通常情况下,程序并不仅仅局限于根据给定的类型参数存储数据,而是经常需要使用类型参数的成员来执行程序泛型中的语句。
为什么需要约束
假设在 Dictionary 类的 Add 方法中,您需要使用所提供的键的 CompareTo 方法比较项目,例如:
public class Dictionary
{
public void Add(KeyType key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
}
}
遗憾的是,正如预期那样,类型参数 KeyType 在编译时是泛型。如果这样编写,编译器假设对类型参数为 KeyType 的 key 实例只能执行适用于基本对象类型(例如 ToString)的操作。结果,由于 CompareTo 方法未定义,编译器将显示编译错误。然而,程序可以将 key 变量转换为包含 CompareTo 方法的对象,例如 IComparable 接口。在以下示例中,程序将 KeyType 参数类型的实例 key 显式转换为程序可以编译的 IComparable 接口:
public class Dictionary
{
public void Add(KeyType key, ValType val)
{
...
switch(((IComparable) key).CompareTo(x))
{
}
...
}
}
然而,如果立即实例化 Dictionary 类而且提供的类型参数没有实现 IComparable 接口,则程序将遇到运行时错误,尤其是 InvalidCastException 异常。
声明约束
在 C# 中,程序可以为泛型类中声明的每个类型参数提供可选约束列表。约束表示要将一个类型构造成泛型所必须满足的要求。可以使用 where 关键字声明约束,该关键字后跟“参数-要求”对,其中“参数”必须是泛型中定义的某个参数,“要求”必须是类或接口。
为了满足在 Dictionary 类中使用 CompareTo 方法的需要,程序可以对 KeyType 类型参数添加约束,要求传递给 Dictionary 类作为第一个参数的任何类型都必须实现 IComparable 接口,例如:
public class Dictionary where KeyType : IComparable
{
public void Add(KeyType key, ValType val)
{
...
switch(key.CompareTo(x))
{
}
...
}
}
这样,编译代码时就会检查代码,以确保程序每次使用 Dictionary 类时,作为第一个参数传递的类型都实现了 IComparable 接口。此外,程序在调用 CompareTo 方法之前,再也无需将变量显式转换为 IComparable 接口了。
|