泛型类封装不是特定于具体数据类型的操作。泛型类最常用于集合,如链表、哈希表、堆栈、队列、树等,其中,像从集合中添加和移除项这样的操作都以大体上相同的方式执行,与所存储数据类型无关。
一般情况下,创建泛型类的过程为:从一个现有的具体类开始,逐一将每个类型更改为类型参数,直至达到通用化和可用性的最佳平衡。创建您自己的泛型类时,需要特别注意以下事项:
将那些类型通用化为类型参数。
一般规则是,能够参数化的类型越多,代码就会变得越灵活,重用性就越好,但是,太多的通用化会使其他开发人员难以阅读或理解代码。
如果存在约束,应对类型参数应用什么约束
一个有用的规则是,应用尽可能最多的约束,但仍使您能够处理需要处理的类型。例如,如果您知道您的泛型类仅用于引用类型,则应用约束。这可以防止您的类被意外地用于值类型,并允许您对T使用as运算符以及检查空值。
是否将泛型行为分解为基类和子类
由于泛型类可以作为基类使用,此处适用的设计注意事项和非泛型类相同。
是否实现一个或多个泛型接口
例如,如果您设计一个类,该类将用于创建基于泛型的集合中的项,则可能需要实现一个接口,如IComparable<T>,其中T是您类的类型。
类型参数和约束的规则对于泛型类型为有几方面的含义,特别是关于继承和成员可访问性。请务必先理解一些术语,然后再继续进行。对于泛型类Node<T>,客户端代码通过指定类型参数引用该类,以创建封闭式构造类型Node<int>,或者可以让类型参数处于未指定状态(例如在指定泛型基类时)以创建开放式构造类型(Node<T>).泛型类可以从具体的、封闭式构造或开放式构造基类继承
泛型类型定义与构造泛型类型
如果要创建一个类型的实例,则需要知道它是一个泛型类型定义还是一个构造泛型类型。
泛型类型定义有一个或多个未满足的类型占位符,换句话说,泛型类型定义不知道它自己的参数类型。
构造泛型类型的类型占位符已替换为具体类型。你无法创建非构造泛型类型的实例,在试图创建实例前,你必须提供具体类型。
泛型类型定义 + 指定类型占位符 ---------> 构造泛型类型
可以使用type.IsGenericTypeDefinition,来判断当前Type是否表示可以用来构造其他泛型类型的泛型类型定义。
Dim type1 As Type = GetType(Dictionary(Of ,))
Dim type2 As New Dictionary(Of String, DateTime)
Dim type3 As Type = type2.GetType()
'使用type.GetGenericTypeDefinition 方法检索其泛型类型的定义
Dim type4 As Type = type3.GetGenericTypeDefinition()
'type1.Name:Dictionary`2
AddToResults("type1.Name:{0}", type1.Name)
'type1 is generic type definition:True
AddToResults("type1 is generic type definition:{0}", type1.IsGenericTypeDefinition)
'type3.Name:Dictionary`2
AddToResults("type3.Name:{0}", type3.Name)
'Type3 是构造泛型类型,而不是泛型类型定义
'type3 is generic type definition:False
AddToResults("type3 is generic type definition:{0}", type3.IsGenericTypeDefinition)
'type4 is generic type definition:True
AddToResults("type4 is generic type definition:{0}", type4.IsGenericTypeDefinition)
AddToResults()
'比较type1和type4的引用;它们应该是完全相同的引用(Dictionary实例的泛型类型定义)。
' type1 is type4?:True
AddToResults("type1 is type4?:{0}", type1 Is type4)
判断泛型类型定义、以及判断泛型类型是封闭式泛型,还是开放式泛型
Private Sub DisplayGenericTypeInfo(ByVal t As Type)
AddToResults("{0}", t)
Dim indent As String = vbTab
'判断是否是泛型定义
AddToResults("{0}Generic type definition :{1}", indent, t.IsGenericTypeDefinition)
'判断是否是泛型
AddToResults("{0}Generic type :{1}", indent, t.IsGenericType)
'判断是封闭式泛型,还是开放式泛型;如果是开放式,
‘则该属性返回true。开放式泛型,不能直接创建该类型的实例
AddToResults("{0} Unassigned generic parameters:{1}", indent, t.ContainsGenericParameters)
'返回表示泛型类型的类型实参,或泛型类型定义的类型形参的Type对象的数组
Dim args() As Type = t.GetGenericArguments()
AddToResults("{0}List type arguments ({1}):", indent, args.Length)
For Each argType As Type In args
AddToResults("{0}{0}{1}", indent, argType)
Next
AddToResults("{0}{1}", indent, IIf(t.ContainsGenericParameters, "Open", "Closed"))
End Sub
通过下面代码,对上面方法(DisplayGenericTypeInfo)进行使用.先提供一个泛型类BaseClass(of ,)
Public Class BaseClass(Of T, U) Public Items As New Dictionary(Of T, U) Public Sub New() Debug.Print("In BaseClass,GetType(T) = " & GetType(T).Name) Debug.Print("In BaseClass,GetType(U) = " & GetType(U).Name) End Sub End Class
- 然后使用该类,下面代码显示了如何在给定一个泛型类型定义的情况下,创建一个封闭式泛型类型。
- 同时,代码在运行时,创建一个构造类型,并与设计时创建的构造类型相比较
Private Sub CreateGenericTypeGivenGenericTypeDefinition() 'given a generic type definition ,generate a generic type Dim type1 As Type = GetType(BaseClass(Of ,)) DisplayGenericTypeInfo(type1) 'create an array of types to substitute for the type paramters Dim args() As Type = {GetType(String), GetType(DateTime)} 'create a Type object representing the constructed generic type Dim constructed As Type = type1.MakeGenericType(args) DisplayGenericTypeInfo(constructed) Dim type2 As Type = GetType(BaseClass(Of String, DateTime)) AddToResults("Constructed types equal:{0}", constructed Is type2) AddToResults("Generic types equals:{0}", type2.GetGenericTypeDefinition Is type1) End Sub