1、泛型引入緩存
需求:傳入一個類型(整型/日期/字符串或其餘),打印出它的類型和內容。 ide
1.初級版函數
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="dParameter"></param> 27 public static void ShowDateTime(DateTime dParameter) 28 { 29 Console.WriteLine("This is {0},parameter={1},type={2}", 30 typeof(CommonMethod).Name, dParameter.GetType().Name, dParameter); 31 } 32 }
typeof和gettype的區別spa
調用.net
1 static void Main(string[] args) 2 { 3 DateTime dt = DateTime.Now; 4 int i = 5; 5 string test = "test"; 6 object o = new object(); 7 CommonMethod.ShowDateTime(dt); 8 CommonMethod.ShowInt(i); 9 CommonMethod.ShowString(test); 10 }
2.升級版pwa
1 /// <summary> 2 /// 打印object值 3 /// 1.object是一切類型的基礎 4 /// 2.經過集成,子類擁有父類的一切屬性和行爲 5 /// </summary> 6 /// <param name="o"></param> 7 public static void ShowObject(object oParameter) 8 { 9 Console.WriteLine("This is {0},parameter={1},type={2}", 10 typeof(CommonMethod).Name, oParameter.GetType().Name, oParameter); 11 }
調用3d
1 DateTime dt = DateTime.Now; 2 int i = 5; 3 string test = "test"; 4 object o = new object(); 5 CommonMethod.ShowObject(dt); 6 CommonMethod.ShowObject(i); 7 CommonMethod.ShowObject(test); 8 CommonMethod.ShowObject(o);
缺點:若是傳遞的是值類型,會裝箱拆箱調試
2、泛型來嘍code
定義泛型blog
1 public class GenericMethod 2 { 3 /// <summary> 4 /// 方法名字後面帶上尖括號 類型參數 5 /// T能夠換成其餘任何未定義的名稱,可是不要用關鍵字、類名等等 6 /// 來自 .net framework2.0 CLR升級的 7 /// 解決相同內容/操做,對於不一樣參數的問題 8 /// 9 /// 延遲聲明,聲明方法的時候沒有指定參數類型,而是等到調用的時候指定 10 /// 延遲思想:推遲一切能夠推遲的 11 /// 12 /// 編譯的時候 類型參數編譯爲佔位符 `(1旁邊英文輸入狀態) 13 /// 程序運行的時候,jit即時編譯替換爲真實類型 14 /// 15 /// 16 /// </summary> 17 /// <param name="o"></param> 18 public static void Show<T>(T tParameter) 19 { 20 Console.WriteLine("This is {0},parameter={1},type={2}", 21 typeof(CommonMethod).Name, tParameter.GetType().Name, tParameter); 22 } 23 }
調用
1 GenericMethod.Show<DateTime>(dt); 2 GenericMethod.Show(dt);//不指定類型參數,編譯器自動推算(編譯器的語法糖) 3 GenericMethod.Show<int>(i); 4 GenericMethod.Show<string>(test); 5 GenericMethod.Show<object>(o);
3、消耗時間對比
1 using System; 2 using System.Diagnostics; 3 4 namespace MyGeneric 5 { 6 public class Monitor 7 { 8 public static void Show() 9 { 10 Console.WriteLine("******************Monitor****************"); 11 int iValue = 123456; 12 long commonSecond = 0; 13 long objectSecond = 0; 14 long genericSecond = 0; 15 16 { 17 Stopwatch watch = new Stopwatch(); 18 watch.Start(); 19 for (int i = 0; i < 100000000; i++) 20 { 21 ShowInt(iValue); 22 } 23 watch.Stop(); 24 commonSecond = watch.ElapsedMilliseconds; 25 } 26 27 { 28 Stopwatch watch = new Stopwatch(); 29 watch.Start(); 30 for (int i=0;i<100000000;i++) 31 { 32 ShowObject(iValue); 33 } 34 watch.Stop(); 35 objectSecond = watch.ElapsedMilliseconds; 36 } 37 { 38 Stopwatch watch = new Stopwatch(); 39 watch.Start(); 40 for (int i = 0; i < 100000000; i++) 41 { 42 Show(iValue); 43 } 44 watch.Stop(); 45 genericSecond = watch.ElapsedMilliseconds; 46 } 47 Console.WriteLine("commonSecond={0},objectSecond={1},genericSecond={2}", 48 commonSecond, objectSecond, genericSecond); 49 Console.Read(); 50 } 51 52 53 public static void ShowInt(int iParameter) 54 { 55 //do nothing 56 } 57 58 59 public static void ShowObject(object oParameter) 60 { 61 //do nothing 62 } 63 64 public static void Show<T>(T tParameter) 65 { 66 //do nothing 67 } 68 } 69 }
調試啓動的時間以下,能夠看出泛型執行的時間是最短的。
若是更換順序,將執行泛型的方法放到第一位的話,會出現泛型時間和普通時間同樣,甚至還會比它耗費時間長的狀況。
ctrl+F5啓動時間對好比下(這一塊不懂,爲何普通方法要比泛型的時間快呢)
4、泛型類
1 using System; 2 3 namespace MyGeneric 4 { 5 //泛型類 6 public class GenericClass<W,Jasmine,Apple>//參數類型能夠隨便指定,意思就是至關於在這個類中定義了一個w的類型 7 { 8 public void Show(W w) { } 9 public Jasmine Get() 10 { 11 return default(Jasmine); 12 } 13 } 14 /// <summary> 15 /// 泛型接口 16 /// </summary> 17 /// <typeparam name="T"></typeparam> 18 public interface IStudy<T> 19 { 20 T Study(T t); 21 } 22 public delegate Everything GetHandler<Everything>();//泛型委託 23 24 /// <summary> 25 /// 普通類 26 /// </summary> 27 public class Child 28 //: GenericClass<string,int,string> //指定類型參數後便可繼承 29 //:GenericClass<W, Jasmine, Apple> 這種寫法是錯誤的,普通類不能直接繼承泛型類 30 //:IStudy<T> 普通類不能直接實現泛型接口 31 : IStudy<string> 32 { 33 public string Study(string t) 34 { 35 throw new NotImplementedException(); 36 } 37 } 38 39 40 public class GenericChild<W,Jasmine, Apple> 41 //: GenericClass<W,Jasmine,Apple> //泛型類能夠直接繼承泛型類 42 //public class GenericChild<W, Jasmine>//等於聲明瞭兩個局部類型 W和Jasmin 43 //: GenericClass<W, Jasmine, string> 44 :IStudy<W> //泛型類不能直接實現泛型接口 45 { 46 public W Study(W t) 47 { 48 throw new NotImplementedException(); 49 } 50 } 51 52 }
5、泛型約束
1.所需模型
1 using System; 2 3 namespace MyGeneric 4 { 5 public class Model 6 { 7 public class People 8 { 9 public int Id { get; set; } 10 public string Name { get; set; } 11 public void Hi() 12 { 13 } 14 } 15 16 public interface ISports 17 { 18 void PingPang(); 19 } 20 21 public interface IWork 22 { 23 void Work(); 24 } 25 26 public class Chinese : People,ISports,IWork 27 { 28 public void Tradition() 29 { 30 Console.WriteLine("謙虛"); 31 } 32 public void SayHi() 33 { 34 } 35 36 public void PingPang() 37 { 38 throw new NotImplementedException(); 39 } 40 41 public void Work() 42 { 43 throw new NotImplementedException(); 44 } 45 } 46 47 public class Sichuan : Chinese 48 { 49 public string Panda { get; set; } 50 public void Huoguo() 51 { 52 Console.WriteLine("吃火鍋啦"); 53 } 54 } 55 } 56 57 }
2.泛型約束(基類約束)
1 using System; 2 using static MyGeneric.Model; 3 4 namespace MyGeneric 5 { 6 public class Constraint 7 { 8 /// <summary> 9 /// 有約束纔有自由,有權利就得有義務 10 /// 11 /// 1.基類約束,就能夠訪問基類的方法和屬性(基類/子類) 12 /// </summary> 13 /// <typeparam name="T"></typeparam> 14 /// <param name="tParameter"></param> 15 public static void Show<T>(T tParameter) where T : People //基類約束 16 { 17 Console.WriteLine("This is {0},parameter={2},type={1}", 18 typeof(CommonMethod).Name, tParameter.GetType().Name, tParameter); 19 20 Console.WriteLine(tParameter.Id); 21 Console.WriteLine(tParameter.Name); 22 tParameter.Hi(); 23 } 24 } 25 }
調用
1 People people = new People() 2 { 3 Id = 1, 4 Name = "張三" 5 }; 6 Chinese chinese = new Chinese() 7 { 8 Id = 2, 9 Name = "李四" 10 }; 11 Sichuan sichuan = new Sichuan() 12 { 13 Id = 3, 14 Name = "小紅" 15 }; 16 17 Constraint.Show(people); 18 Constraint.Show(chinese); 19 Constraint.Show(sichuan);
3.泛型約束(接口約束)
1 public static void ShowSports<T>(T tParameter) where T : ISports //基類約束 2 { 3 Console.WriteLine("This is {0},parameter={2},type={1}", 4 typeof(CommonMethod).Name, tParameter.GetType().Name, tParameter); 5 6 tParameter.PingPang(); 7 }
調用和上面的相同,實現了該接口的類,可直接當作參數傳入。
4.其餘泛型約束寫法
1 public static T Get<T>() 2 //where T:class //引用類型約束 3 //where T:struct//值類型約束 4 where T:new() //無參數構造函數約束 5 { 6 T t = new T(); 7 return default(T); 8 }
6、協變
1.相關模型(Sparrow是Bird的子類)
1 public class Bird 2 { 3 } 4 5 public class Sparrow : Bird 6 { 7 }
2.
1 Bird bird1 = new Bird(); 2 //左邊父類,右邊子類 3 Bird bird2 = new Sparrow(); 4 Sparrow sparrow1 = new Sparrow(); 5 List<Bird> birdList1 = new List<Bird>(); 6 //List<Bird> bird3 = new List<Sparrow>(); //不是父子關係,沒有繼承關係 7 8 List<Bird> birdlist2 = new List<Sparrow>().Select(s => (Bird)s).ToList();
3.查看IEnumerable定義,能夠看到有一個關鍵字out
4.下面可實現左邊是父類,右邊是子類
1 //協變 2 IEnumerable<Bird> birdList4 = new List<Bird>(); 3 IEnumerable<Bird> birdList5 = new List<Sparrow>();//協變
5.具體應用
1 /// <summary> 2 /// out協變 只能是返回值 3 /// 協變逆變只存在於接口或者委託 4 /// </summary> 5 /// <typeparam name="T"></typeparam> 6 public interface ICustomerListOut<out T> 7 { 8 T Get(); 9 //void Show(T t); // 此處錯誤,T不能做爲傳入參數 10 } 11 12 /// <summary> 13 /// 類沒有協變逆變 14 /// </summary> 15 /// <typeparam name="T"></typeparam> 16 public class CustomerListOut<T> : ICustomerListOut<T> 17 { 18 public T Get() 19 { 20 return default(T); 21 } 22 }
調用
1 ICustomerListOut<Bird> customerList = new CustomerListOut<Bird>(); 2 ICustomerListOut<Bird> customerList1 = new CustomerListOut<Sparrow>(); //協變
7、逆變
1.定義
1 public interface ICustomerListIn<in T> 2 { 3 //T Get(); 4 5 void Show(T t); 6 } 7 8 /// <summary> 9 /// 逆變 只能做爲參數傳入 10 /// </summary> 11 /// <typeparam name="T"></typeparam> 12 public class CustomerListIn<T> : ICustomerListIn<T> 13 { 14 //T Get(); //不能做爲返回值 15 16 public void Show(T t) 17 { 18 } 19 }
2.調用
1 //逆變 2 ICustomerListIn<Sparrow> customerList2 = new CustomerListIn<Sparrow>(); 3 ICustomerListIn<Sparrow> customerList3 = new CustomerListIn<Bird>(); //左邊是子類的時候,右邊能夠是父類 4 5 ICustomerListIn<Bird> birdList6 = new CustomerListIn<Bird>(); 6 birdList6.Show(new Sparrow()); 7 birdList6.Show(new Bird());
8、協變逆變混合應用
1.定義
1 public interface IMyList<in inT, out outT> 2 { 3 void Show(inT t); 4 outT Get(); 5 outT Do(inT t); //out只能是返回值 in只能是參數 6 } 7 8 public class MyList<T1, T2> : IMyList<T1, T2> 9 { 10 11 public void Show(T1 t) 12 { 13 Console.WriteLine(t.GetType().Name); 14 } 15 public T2 Get() 16 { 17 Console.WriteLine(typeof(T2).Name); 18 return default(T2); 19 } 20 public T2 Do(T1 t) 21 { 22 Console.WriteLine(t.GetType().Name); 23 Console.WriteLine(typeof(T2).Name); 24 return default(T2); 25 } 26 }
2.調用
1 IMyList<Sparrow, Bird> myList1 = new MyList<Sparrow, Bird>(); 2 IMyList<Sparrow, Bird> myList2 = new MyList<Sparrow, Sparrow>(); //協變 3 IMyList<Sparrow, Bird> myList3 = new MyList<Bird, Bird>(); //逆變 4 IMyList<Sparrow, Bird> myList4 = new MyList<Bird, Sparrow>(); //逆變
9、泛型緩存
不太懂,有時間再好好研究下(捂臉......)