泛型是程序設計語言的一種特性。容許程序員在強類型程序設計語言中編寫代碼時定義一些可變部分,那些部分在使用前必須做出指明。各類程序設計語言和其編譯器、運行環境對泛型的支持均不同。將類型參數化以達到代碼複用提升軟件開發工做效率的一種數據類型。泛型類是引用類型,是堆對象,主要是引入了類型參數這個概念。程序員
.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 }