码迷,mamicode.com
首页 > Windows程序 > 详细

【C#进阶学习】泛型

时间:2019-03-05 23:12:20      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:code   引用   commons   gen   jasmine   name   属性   ctr   一个   

一、泛型引入

  需求:传入一个类型(整型/日期/字符串或其他),打印出它的类型和内容。  

 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的区别

调用

技术图片
 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.升级版

技术图片
 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

 调用

技术图片
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

 缺点:如果传递的是值类型,会装箱拆箱

二、泛型来喽

定义泛型

技术图片
 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

三、消耗时间对比

技术图片
 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启动时间对比如下(这一块不懂,为什么普通方法要比泛型的时间快呢)

技术图片

 四、泛型类

技术图片
 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

五、泛型约束

 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

 六、协变

  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

 七、逆变

 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

  八、协变逆变混合应用

  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

   九、泛型缓存

   不太懂,有时间再好好研究下(捂脸......)

【C#进阶学习】泛型

标签:code   引用   commons   gen   jasmine   name   属性   ctr   一个   

原文地址:https://www.cnblogs.com/jas0203/p/10383606.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!