泛型是程序设计语言的一种特性。容许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须做出指明。各类程序设计语言和其编译器、运行环境对泛型的支持均不同。将类型参数化以达到代码复用提升软件开发工做效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念。程序员
.net framework1.0时代,若是有如下需求,须要传递不一样类型变量的值,而且打印该变量的值。express
1 /// <summary> 2 /// 打印个int值 3 /// </summary> 4 /// <param name="iParameter"></param> 5 public static void ShowInt(int iParameter) 6 { 7 Console.WriteLine("This is {0},parameter={1},value={2}", typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter); 8 } 9 /// <summary> 10 /// 打印个string值 11 /// </summary> 12 /// <param name="sParameter"></param> 13 public static void ShowString(string sParameter) 14 { 15 Console.WriteLine("This is {0},parameter={1},value={2}", typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter); 16 } 17 /// <summary> 18 /// 打印个DateTime值 19 /// </summary> 20 /// <param name="oParameter"></param> 21 public static void ShowDateTime(DateTime dtParameter) 22 { 23 Console.WriteLine("This is {0},parameter={1},value={2}", typeof(CommonMethod).Name, dtParameter.GetType().Name, dtParameter); 24 }
1 /// <summary> 2 /// 打印个object值 3 /// 1 任何父类出现的地方,均可以用子类来代替,object是一切类型的父类 4 /// 2 使用Object产生两个问题:装箱拆箱、类型安全 5 /// </summary> 6 /// <param name="oParameter"></param> 7 public static void ShowObject(object oParameter) 8 { 9 Console.WriteLine("This is {0},parameter={1},value={2}", typeof(CommonMethod), oParameter.GetType().Name, oParameter); 10 }
1 /// <summary> 2 /// 泛型方法 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 /// <param name="tParameter"></param> 6 public static void Show<T>(T tParameter)//, T t = default(T 7 { 8 Console.WriteLine("This is {0},parameter={1},type={2}", typeof(CommonMethod), tParameter.GetType().Name, tParameter); 9 }
方法名称后面加上尖括号,<>里面是类型参数,类型参数实际上就是一个不肯定类型T声明,声明事后方法就能够用这个不肯定类型T了。在声明泛型时,并无写死类型,T是什么?不知道,T要等着调用的时候才指定。正是由于没有写死,才拥有了无限的可能!!编程
延迟声明:推迟一切能够推迟的,一切能晚点再作的事儿,就晚点再作。深刻一下,泛型的原理,泛型在代码编译时,究竟生成了一个什么东西?泛型不是一个简单的语法糖,是框架升级支持的。泛型方法的性能跟普通方法一致,是最好的,并且还能一个方法知足多个不一样类型。缓存
1.在程序编码中一些包含类型参数的类型,也就是说泛型的参数只能够表明类,不能表明个别对象。(这是当今较常见的定义)安全
2.在程序编码中一些包含参数的类。其参数能够表明类或对象等等。(人们大多把这称做模板)不论使用哪一个定义,泛型的参数在真正使用泛型时都必须做出指明。框架
一些强类型编程语言支持泛型,其主要目的是增强类型安全及减小类转换的次数,但一些支持泛型的编程语言只能达到部分目的。编程语言
泛型是具备占位符(类型参数)的类、结构、接口和方法,这些占位符是类、结构、接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类能够将类型参数用做它所存储的对象的类型的占位符;类型参数做为其字段的类型及其方法的参数类型出现。泛型方法能够将其类型参数用做其返回值的类型或者其某个形参的类型。函数
因为.NET Framework 泛型的类型参数之实际类型在运行时均不会被消除,运行速度会由于类型转换的次数减小而加快。性能
1 Console.WriteLine(typeof(List<>)); 2 Console.WriteLine(typeof(Dictionary<,>));
打印结果:编码
1 public List<T> GetList<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T : class, new() 2 { 3 SqlSugarClient ssc = new SugarHelper(ConnectionKey).GetSqlSugarClient(); 4 List<T> t = ssc.Queryable<T>().Where(expression).ToList(); 5 if (t != null && t.Count > 0) 6 { 7 return t; 8 } 9 return null; 10 }
public interface GenericInterface<T> {
}
容许对个别泛型的类型参数进行约束,包括如下几种形式(假设 C是泛型的类型参数, 是通常类、泛类,或是泛型的类型参数):T 是一个类。T 是一个值类型。T 具备无参数的公有建构方法。T 实现接口 I 。T 是 C ,或继承自 C 。
没有约束,其实很受局限,自由主义的鼻祖洛克先生说过,有了法律,才有自由,其实自由都是相对的。基类约束:where T:BaseModel能够把T当成基类,T必须是BaseModel或者其子类。为何要有约束?Eg:红绿灯约束,绿灯行(权利)、红灯停(约束),由于有约束才有绿灯行的权利。
示例:
public class People { public int Id { get; set; } public string Name { get; set; } public void Hi() { } }
/// <summary> /// 基类约束,T必须是People或People的子类 /// </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(GenericConstraint), tParameter.GetType().Name, tParameter); Console.WriteLine($"{tParameter.Id} {tParameter.Name}"); tParameter.Hi(); }
1 /// <summary> 2 /// 引用类型约束,T必须是一个引用类型 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 /// <returns></returns> 6 public T GetT<T>() where T : class 7 { 8 return null; 9 }
1 /// <summary> 2 /// 值类型约束 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 /// <returns></returns> 6 public T ShowT<T>() where T : struct 7 { 8 return default(T); //default是个关键字,会根据T的类型去得到一个默认值 9 }
1 /// <summary> 2 /// 无参数构造函数 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 /// <typeparam name="S"></typeparam> 6 /// <returns></returns> 7 public T GetT<T, S>() where T : new() 8 { 9 return new T(); 10 }
1 /// <summary> 2 /// 多个约束 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 /// <typeparam name="S"></typeparam> 6 /// <returns></returns> 7 public T GetT_<T, S>() 8 where T : People, IWork, new() 9 { 10 return new T(); 11 }
1 /// <summary> 2 /// 多个参数一致性约束,表示T和S都必须是People或People的子类 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 /// <typeparam name="S"></typeparam> 6 /// <returns></returns> 7 public T FindT<T, S>() where T : People where S : T 8 { 9 return null; 10 }
ps:不能使用密封类约束,由于没有意义。
每一个不一样的T,都会生成一份不一样的副本,适合不一样类型,须要缓存一份数据的场景,效率高。
1 /// <summary> 2 /// 每一个不一样的T,都会生成一份不一样的副本,适合不一样类型,须要缓存一份数据的场景,效率高。 3 /// </summary> 4 /// <typeparam name="T"></typeparam> 5 public class GenericCache<T> 6 { 7 static GenericCache() 8 { 9 Console.WriteLine("This is GenericCache 静态构造函数"); 10 _TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff")); 11 } 12 private static string _TypeTime = ""; 13 public static string GetCache() 14 { 15 return _TypeTime; 16 } 17 }