Generic(泛型)
什么是泛型:“通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用”。
简单来说泛型就是为了使一些代码能够重复利用。
泛型的经历:
在早期.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 }
后来开发人员觉得这样声明太麻烦了,提出了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 }
但是声明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 }
泛型的思想: 延迟声明,把参数类型的声明推迟到调用
但是单单这样声明一个泛型方法是有缺陷的,比如说声明一个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 }
不信的可以用上面的泛型方法试试,只会出现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>(); }