什么是泛型:“通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用”。
简单来说泛型就是为了使一些代码能够重复利用。
泛型的经历:
在早期.net框架中不同的参数类型需要声明不同的方法;
1 public class CommonMethod
2 {
3 /// <summary>
4 /// 打印个int值
5 /// </summary>
6 /// <param name="iParameter"></param>
7 public static void ShowInt(int iParameter)
8 {
9 Console.WriteLine("This is {0},parameter={1},type={2}",
10 typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter);
11 }
12
13 /// <summary>
14 /// 打印个string值
15 /// </summary>
16 /// <param name="sParameter"></param>
17 public static void ShowString(string sParameter)
18 {
19 Console.WriteLine("This is {0},parameter={1},type={2}",
20 typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter);
21 }
22
23 /// <summary>
24 /// 打印个DateTime值
25 /// </summary>
26 /// <param name="oParameter"></param>
27 public static void ShowDateTime(DateTime dtParameter)
28 {
29 Console.WriteLine("This is {0},parameter={1},type={2}",
30 typeof(CommonMethod).Name, dtParameter.GetType().Name, dtParameter);
31 }
32 }
View Code
后来开发人员觉得这样声明太麻烦了,提出了Object参数来替代,因为
1 任何父类出现的地方,都可以使用子类来替换
2 object是一切类型的父类
1 /// <summary>
2 /// 打印个object值
3 /// 1 任何父类出现的地方,都可以使用子类来替换
4 /// 2 object是一切类型的父类
5 /// </summary>
6 /// <param name="oParameter"></param>
7 public static void ShowObject(object oParameter)
8 {
9 //((People)tParameter).Id
10 Console.WriteLine("This is {0},parameter={1},type={2}",
11 typeof(CommonMethod), oParameter.GetType().Name, oParameter);
12 }
13 }
View Code
但是声明object参数方法调用时会经常的进行装箱拆箱,这样会影响程序的运行效率。
后来在.net2.0框架中引用的泛型的概念,这就是泛型的由来。
1 public class GenericMethod
2 {
3 /// <summary>
4 /// </summary>
5 /// <typeparam name="T"></typeparam>
6 /// <param name="tParameter"></param>
7 public static void Show<T>(T tParameter)
8 {
9 Console.WriteLine("This is {0},parameter={1},type={2}",
10 typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());
11 }
12 }
View Code
泛型的思想: 延迟声明,把参数类型的声明推迟到调用
但是单单这样声明一个泛型方法是有缺陷的,比如说声明一个people对象,想打印出people的属性,单声明一个泛型方法是做不到这个功能的。
1 public class People
2 {
3 public int Id { get; set; }
4 public string Name { get; set; }
5
6 public void Hi()
7 { }
8
9 }
View Code
不信的可以用上面的泛型方法试试,只会出现object下的方法。
这就出现了泛型约束。
泛型约束:它通知编译器,只有这个类型的对象或从这个类型派生的对象,可被用作类型参数。一旦编译器得到这样的保证,它就允许在泛型类中调用这个类型的方法。
按照我的理解就是说,定义了一个泛型后,然后声明一个约束,告诉这个方法是满足哪些条件的约束,这样才能直接使用基类的属性和方法
public class Constraint
{
/// <summary>
/// 泛型约束,基类约束:
/// 1 在泛型方法内可以直接使用基类的属性和方法
/// 2 调用的时候,只能传递基类或者基类的子类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void Show<T>(T tParameter) where T : People
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(GenericMethod), tParameter.GetType().Name, tParameter.ToString());
//((People)tParameter).Id
//tParameter.
Console.WriteLine("id={0} name={1}", tParameter.Id, tParameter.Name);
tParameter.Hi();
}
泛型约束分为下面几种:
约束 | 描述 |
where T: struct | 类型参数必须为值类型。 默认返回return default(T); |
where T : class | 类型参数必须为引用类型。默认返回return null; |
where T : new() | 类型参数必须有一个公有、无参的构造函数。当于其它约束联合使用时,new()约束必须放在最后。 |
where T : <base class name> | 类型参数必须是指定的基类型或是派生自指定的基类型。 |
where T : <interface name> | 类型参数必须是指定的接口或是指定接口的实现。可以指定多个接口约束。接口约束也可以是泛型的。 |
还有一些关于泛型类、接口、委托的声明。
public class GenericClass<T>
{
public void Show(T t)
{
Console.WriteLine(t);
}
public T Get(T t)
{
List<int> iList = null;
return t;
}
}
public interface IGet<T>
{ }
public delegate void GetHandler<T>();
}