为什么要使用泛型
考虑一种堆栈类
class Stack
{
public string[] Elements { get; set; }
public int Current { get; set; }
public string Pop()
{
return Elements[Current];
}
public void Push(string element)
{
}
}
上述堆栈类的元素是字符串类型,但实际开发中可能运用到很多不同的类型,甚至是自定义的类型。显然我们不可能为每一个类型新建一个“Stack”类。
简单的泛型应用
泛型类型参数
在C++模板中,使用“T”代表一个模板类型。这种用法同样延续到了C#中。
此外,还可以以T开头选择更加符合语境的词语,例如:
Dictionary<TKey,TValue>。
在泛型类型或泛型方法定义中,使用"T",以“T”为前缀的描述性词语,作为该泛型的类型参数更加符合规范。
泛型在类中
对于上述的Stack类,可以改写为如下形式
class Stack<TElement>
{
public TElement[] Elements { get; set; }
public int Current { get; set; }
public TElement Pop()
{
return Elements[Current];
}
public void Push(string element)
{
}
}
泛型在接口中
泛型在接口中广泛运用,特别是泛型集合类。
在System.Collections.Generic下存在大量泛型接口
泛型在接口中的简单使用如下:
interface IInterface<T>
{
void fun1(T t);
T fun2();
}
泛型在方法中
泛型也可以在方法中使用,代表一个使用类型参数声明的方法。 代码示例
public void Swap<T>(ref T lhs,ref T rhs)
{
}
泛型约束
定义泛型时,可以对泛型类或泛型接口,方法能够接收的类型参数的种类加以限制。在编译阶段,如果使用不符合要求的类作为类型参数,则会产生编译错误。
泛型约束的声明格式
使用where关键字指定泛型约束
泛型约束使用where关键字指定。例如,要限制一个泛型类必须具有无参数公共构造函数,代码如下:
class Stack<TElement> where TElement :new()
六种约束的格式说明
where T:struct
class Stack<TElement> where TElement :struct
限制类型参数必须是值类型,并且不可以是可空值类型(例如int?,char?,double?,bool?等) where T: class
class Stack<TElement> where TElement :class
限制类型参数必须是引用类型 where T:基类名
class Stack<TElement> where TElement :BaseClass
限制类型参数必须是继承自指定的基类,或是基类本身 where T:接口名
class Stack<TElement> where TElement :IInterface
限制类型参数必须是实现指定接口,或是指定接口 where T:new()
class Stack<TElement> where TElement :new()
限制类型参数必须具有无参构造函数
泛型约束的意义
泛型约束可以保证传递的类型参数符合一定的条件,并且在编译阶段就可以进行验证:例如添加T: new()约束可以保证传递的类型参数一定包含无参构造函数,添加基类约束可以保证类型一定派生自某个基类。
有了上面的保证,我们就可以在泛型类中调用T类型的构造函数,或者调用其基类的方法。
例如:
为Stack类添加约束
(注意构造器约束需要放在最后)
public class Stack<TElement> where TElement :Paper,new()
{
public TElement[] Elements { get; set; }
public int Current { get; set; }
public Paper Pop()
{
TElement element = new TElement();
element = Elements[Current];
return element.DrawOutTissue();
}
public void Push(string element)
{
}
}
public class Paper
{
Paper()
{
}
Paper DrawOutTissue()
{
return new Paper();
}
}
泛型约束的一些复杂情况
多个约束
对一个泛型参数可以添加多个约束,例如,可以同时为上述”class Stack “ 添加 class,new(),Paper,
但是:
- 不可能同时添加struct和class约束
- 不可能添加多个基类约束
- 约束之间是 and 关系,不能添加or关系的约束
- 构造器约束必须最后
- 构造器约束只能指明无参构造器
- 约束不会继承
多个参数
对于一种表示“键值对”关系的泛型类KeyValue<TKey,TValue>,该类具有两个泛型参数TKey,TValue,要为其都添加约束,代码如下:
public class KeyValue<TKey,TValue> where TKey : new()
where TValue: Base,new()
|
请发表评论