以前在做项目的时候,也经常会使用到泛型,但是对于泛型接口、泛型约束等总是理解的比较模糊,现在将泛型的使用总结如下
1、泛型约束
1.1、泛型约束说明
在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的。下表列出了六种类型的约束:
1.2、使用约束的原因
如果要检查泛型列表中的某个项以确定它是否有效,或者将它与其他某个项进行比较,则编译器必须在一定程度上保证它需要调用的运算符或方法将受到客户端代码可能指定的任何类型参数的支持。这种保证是通过对泛型类定义应用一个或多个约束获得的。例如,基类约束告诉编译器:仅此类型的对象或从此类型派生的对象才可用作类型参数。一旦编译器有了这个保证,它就能够允许在泛型类中调用该类型的方法。约束是使用上下文关键字 where 应用的,下面的代码示例演示可通过应用基类约束添加到 GenericList 类(在泛型介绍(C# 编程指南)中)的功能。
public class Person
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
public class GenericList<T> where T:Person
{
private class Node
{
private Node next;
private T data;
public Node(T t)
{
next = null;
data = t;
}
public Node Next
{
get { return next; }
set { next = value; }
}
public T Data
{
get { return data; }
set { data = value; }
}
}
private Node head;
public GenericList() //constructor
{
head = null;
}
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
public T FindFirstOccur(string s)
{
Node current = head;
T t = null;
while (current != null)
{
//The constraint enables access to the Name property.
if (current.Data.Name == s)
{
t = current.Data;
break;
}
else
{
current = current.Next;
}
}
return t;
}
}
约束使得泛型类能够使用 Person.Name 属性,因为类型为 T 的所有项都保证是 Person 对象或从 Person 继承的对象。
可以对同一类型参数应用多个约束,并且约束自身可以是泛型类型,如下所示:
class PersonList<T> where T : Person, IPerson, System.IComparable<T>, new()
{
// ...
}
更多详情:类型参数的约束
2、泛型类
3、泛型接口
泛型类与泛型接口暂时没有合适的demo,等以后有合适的了,在补上。
4、泛型方法
泛型方法是使用类型参数声明的方法,如下所示:
class Program
{
static void Swap<T>(ref T lhs, ref T rhs)
{
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
static void Main(string[] args)
{
int a = 1;
int b = 2;
Swap<int>(ref a, ref b);//
System.Console.WriteLine(a + " " + b);
}
}
更多详情:泛型方法
5、泛型委托
class Program
{
public delegate T AddDelegate<T, T1>(T x, T1 y);
public static int Calc(int x,string s)
{
return x + s.Length;
}
static void Main(string[] args)
{
AddDelegate<int, string> addDelegate = new AddDelegate<int, string>(Calc);
int result = addDelegate(1, "abc");
Console.WriteLine(result);
//等价于
AddDelegate<int, string> addDel = Calc;
}
}
6、泛型默认关键字(default)
在泛型类和泛型方法中产生的一个问题是,在预先未知以下情况时,如何将默认值分配给参数化类型 T:
T 是引用类型还是值类型。
如果 T 为值类型,则它是数值还是结构。
给定参数化类型 T 的一个变量 t,只有当 T 为引用类型时,语句 t = null 才有效;只有当 T 为数值类型而不是结构时,语句 t = 0 才能正常使用。解决方案是使用 default 关键字,此关键字对于引用类型会返回空,对于数值类型会返回零。对于结构,此关键字将返回初始化为零或空的每个结构成员,具体取决于这些结构是值类型还是引用类型。以下来自 GenericList 类的示例显示了如何使用 default 关键字
public class GenericList<T>
{
private class Node
{
//...
public Node Next;
public T Data;
}
private Node head;
//...
public T GetNext()
{
T temp = default(T);
Node current = head;
if (current != null)
{
temp = current.Data;
current = current.Next;
}
return temp;
}
}
参考资料
1、泛型(C#编程指南)