一、什么是泛型
泛型是具有占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的对象的类型的占位符;类型参数作为其字段的类型及其方法的参数类型出现。泛型方法可以将其类型参数用作其返回值的类型或者其某个形参的类型。
二、为什么使用泛型
在编码过程中,我们常常会遇到相似的模块,只是参数类型不同,就拿Console.WriteLine()来说,只是打印一句话,但是不同类型需要不同的方法,Console.WriteLine有十几个重载方法,如果只是为了让方法通用只需要把参数定义为object类型就可以了,但是调用object类型参数有一个问题就是性能,这是因为调用object类型方法,常常会涉及装箱(值类型→object)和拆箱(object→值类型)
泛型是由CLR(通用语言运行平台 Common Language Runtime)2.0 提供编译的,它的底层原理和我们写一个普通方法是一样的
三、泛型的使用
1)泛型方法
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/// <summary> /// 泛型方法:方法名称后面加上尖括号,里面是类型参数 /// 类型参数实际上就是一个类型T声明,方法就可以用这个类型T了 /// /// 思考下,泛型为什么也可以,支持多种不同类型的参数? /// 泛型声明方法时,并没有写死类型,T是什么,不知道 /// T要等着调用的时候才指定 /// 正是因为没有写死,才拥有了无限的可能!! /// /// 设计思想--延迟声明:推迟一切可以推迟的,一切能晚点再做的事儿,就晚点再做 /// 深入一下,泛型的原理 /// /// 泛型在代码编译时,究竟生成了一个什么东西 /// 泛型不是一个简单的语法糖,是框架升级支持的 /// /// 泛型方法的性能跟普通方法一致,是最好的, /// 而且还能一个方法满足多个不同类型 /// 又叫马儿跑,又叫马儿不吃草,是因为框架的升级支持的!! /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tParameter"></param> public static void Show<T>(T tParameter)//, T t = default(T { Console.WriteLine("This is {0},parameter={1},type={2}", typeof(CommonMethod), tParameter.GetType().Name, tParameter); } //WebServices WCF 都不能用泛型,为什么? //跨语言的,别的语言也能用,不支持泛型。。 //服务在发布的时候是必须确定的,泛型在编译时确定不了
2)泛型接口
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public interface GenericInterface<T> { }
3)泛型类
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class GenericClass<T> { }
4)泛型委托
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public delegate T DoSomething<T>();
四、泛型约束
- 引用类型约束 where T:class 传入类型必须为引用类型
- 值类型约束 where T:struct 传入类型必须为值类型
- 基类约束 where T:BaseClass 传入类型必须为基类或其子类
- 接口约束 where T:Interfaces 传入类型必须实现接口
- 无参数构造函数约束 where T:new () 传入类型必须有无参数的构造函数
- 多重约束 传入类型必须满足所有约束条件
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/// <summary> /// 没有约束,其实很受局限 /// where T:BaseModel /// 基类约束: /// 1 可以把T当成基类---权利 /// 2 T必须是基类或者其子类 ///为什么要有约束? 因为有约束才有权利 ///自由主义的鼻祖洛克先生说过,有了法律,才有自由 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tParameter"></param> public static void Show<T>(T tParameter) //where T : String//密封类约束的不行,因为没有意义 //where T : People //where T : ISports where T : People, ISports, IWork, new() { Console.WriteLine("This is {0},parameter={1},type={2}", typeof(GenericConstraint), tParameter.GetType().Name, tParameter); Console.WriteLine($"{tParameter.Id} {tParameter.Name}"); tParameter.Hi(); //tParameter.Pingpang(); } public T GetT<T, S>() //where T : class//引用类型约束 //where T : struct//值类型 where T : new()//无参数构造函数 where S : class { //return null; //return default(T);//default是个关键字,会根据T的类型去获得一个默认值 return new T(); //throw new Exception(); }
本文参考文档:https://www.cnblogs.com/loverwangshan/p/9871548.html;
微软官方文档地址:https://docs.microsoft.com/zh-cn/dotnet/standard/generics/;
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/;