深入解析C#中的泛型类与泛型接口

2019-12-26 17:32:56于海丽


class BaseNode { }
class BaseNodeGeneric<T> { }

// concrete type
class NodeConcrete<T> : BaseNode { }

//closed constructed type
class NodeClosed<T> : BaseNodeGeneric<int> { }

//open constructed type 
class NodeOpen<T> : BaseNodeGeneric<T> { }

非泛型类(换句话说,即具体类)可以从封闭式构造基类继承,但无法从开放式构造类或类型参数继承,因为在运行时客户端代码无法提供实例化基类所需的类型参数。


//No error
class Node1 : BaseNodeGeneric<int> { }

//Generates an error
//class Node2 : BaseNodeGeneric<T> {}

//Generates an error
//class Node3 : T {}

从开放式构造类型继承的泛型类必须为任何未被继承类共享的基类类型参数提供类型变量,如以下代码所示:


class BaseNodeMultiple<T, U> { }

//No error
class Node4<T> : BaseNodeMultiple<T, int> { }

//No error
class Node5<T, U> : BaseNodeMultiple<T, U> { }

//Generates an error
//class Node6<T> : BaseNodeMultiple<T, U> {} 

从开放式构造类型继承的泛型类必须指定约束,这些约束是基类型约束的超集或暗示基类型约束:


class NodeItem<T> where T : System.IComparable<T>, new() { }
class SpecialNodeItem<T> : NodeItem<T> where T : System.IComparable<T>, new() { }

泛型类型可以使用多个类型参数和约束,如下所示:


class SuperKeyType<K, V, U>
  where U : System.IComparable<U>
  where V : new()
{ }

开放式构造类型和封闭式构造类型可以用作方法参数:


void Swap<T>(List<T> list1, List<T> list2)
{
  //code to swap items
}

void Swap(List<int> list1, List<int> list2)
{
  //code to swap items
}

如果某个泛型类实现了接口,则可以将该类的所有实例强制转换为该接口。
泛型类是不变的。也就是说,如果输入参数指定 List<BaseClass>,则当您尝试提供 List<DerivedClass> 时,将会发生编译时错误。


泛型接口
为泛型集合类或表示集合中项的泛型类定义接口通常很有用。对于泛型类,使用泛型接口十分可取,例如使用 IComparable<T> 而不使用 IComparable,这样可以避免值类型的装箱和取消装箱操作。.NET Framework 类库定义了若干泛型接口,以用于 System.Collections.Generic 命名空间中的集合类。