【C#進階學習】泛型

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     }
View Code

 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         }
View Code

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         }
View Code

 調用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);
View Code

 缺點:若是傳遞的是值類型,會裝箱拆箱調試

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     }
View Code

調用

1             GenericMethod.Show<DateTime>(dt);
2             GenericMethod.Show(dt);//不指定類型參數,編譯器自動推算(編譯器的語法糖)
3             GenericMethod.Show<int>(i);
4             GenericMethod.Show<string>(test);
5             GenericMethod.Show<object>(o);
View Code

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 }
View Code

 調試啓動的時間以下,能夠看出泛型執行的時間是最短的。

 若是更換順序,將執行泛型的方法放到第一位的話,會出現泛型時間和普通時間同樣,甚至還會比它耗費時間長的狀況。

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 }
View Code

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 }
View Code

 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 }
View Code

 調用

 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);
View Code

   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         }
View Code

  調用和上面的相同,實現了該接口的類,可直接當作參數傳入。

 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         }
View Code

 6、協變

  1.相關模型(Sparrow是Bird的子類)

1         public class Bird
2         {
3         }
4 
5         public class Sparrow : Bird
6         {
7         }
View Code

  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();
View Code

   3.查看IEnumerable定義,能夠看到有一個關鍵字out

    4.下面可實現左邊是父類,右邊是子類

1         //協變
2         IEnumerable<Bird> birdList4 = new List<Bird>();
3         IEnumerable<Bird> birdList5 = new List<Sparrow>();//協變
View Code

    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     }
View Code

  調用

1         ICustomerListOut<Bird> customerList = new CustomerListOut<Bird>();
2         ICustomerListOut<Bird> customerList1 = new CustomerListOut<Sparrow>(); //協變
View Code

 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     }
View Code

   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());
View Code

  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     }
View Code

     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>();   //逆變
View Code

   9、泛型緩存

   不太懂,有時間再好好研究下(捂臉......)

相關文章
相關標籤/搜索