1.net基础之泛型

泛型的引入:微软在 .net frameWork 2.0 框架引入了泛型。 泛型的引入解决了代码重复了的问题,将公共逻辑抽象化;增加了代码的性能,泛型通过使用类型占位符预编译在实际调用时传递具体类型参数,进而减少值类型和引用类型的相互装箱 / 拆箱。

  1. 引入泛型
  2. 声明使用泛型
  3. 泛型好处对比性能
  4. 泛型类,泛型方法,泛型接口,泛型委托
  5. 泛型约束
  6. 泛型的逆变,协变  out协变covariant 修饰返回值,in 逆变 contravariant 修饰传入值
  7. 泛型缓存

泛型的声明在没有使用泛型的情况下编写可以接收多种类型的实现相同逻辑的函数通常有两种方式。1,需要什么类型就定义一个接收固定类型的方法,各自方法实现一遍相同的逻辑。2,定义一个函数接收object类型参数。代码如下

 1
 2     public class CommonMethod
 3     {
 4         public static void ShowInt(int iParameter)
 5         {
 6             Console.WriteLine("This is {0},parameter {1},type={2}",
 7                 typeof(CommonMethod).Name, iParameter, iParameter.GetType().Name);
 8         }
 9         public static void ShowString(string sParameter)
10         {
11             Console.WriteLine("This is {0},parameter {1},type={2}",
12                 typeof(CommonMethod).Name, sParameter, sParameter.GetType().Name);
13         }
14         public static void ShowDateTime(DateTime dtParameter)
15         {
16             Console.WriteLine("This is {0},parameter {1},type={2}",
17                 typeof(CommonMethod).Name, dtParameter, dtParameter.GetType().Name);
18         }
19
20
21         /// <summary>
22         /// object是所有类型的父类
23         /// 通过继承,子类拥有父类一切的属性和行为,任何父类出现的地方都可以用子类来代替
24         /// 传递值类型的时候会产生装箱操作
25         /// </summary>
26         /// <param name="obj"></param>
27         public static void ShowObject(object obj) {
28             Console.WriteLine("This is {0},parameter {1},type={2}",
29               typeof(CommonMethod).Name, obj, obj.GetType().Name);
30         }

普通方法和object方法

用第一种方式和第二种方式都可以解决问题。那么他们有各自的缺点。

第一种方式:如果传递十种类型的参数那么就需要定义是个方法,内部逻辑相同这样会产生重复劳动和大量的重复代码。

第二种方式:因为参数为object类型如果传递了值类型就会产生装箱操作,产生程序性能的损耗。

第三种方式:泛型。通过泛型可以解决以上的需求: 传入参数不确定,内部逻辑相同,不会产生性能方面的损耗。

声明使用泛型方法

 1 //泛型方法    ---  有相同逻辑的地方,类型不同或类型不确定的情况下,提高代码重用性
 2         /// <summary>
 3         /// 延迟声明,在声明方法的时候没有指定参数类型,在调用的时候再指定
 4         /// 编译的时候,类型参数编译为占位符
 5         /// 程序运行的时候jit即时编译的时候编译为真实类型
 6         /// </summary>
 7         /// <typeparam name="T">类型参数</typeparam>
 8         /// <param name="tParameter">实际参数</param>
 9         public static void Show<T>(T tParameter) {
10             Console.WriteLine("This is {0},parameter {1},type={2}",
11                 typeof(CommonMethod).Name, tParameter, tParameter.GetType().Name);
12         }

声明泛型方法

 

使用泛型方法和普通方法和object方法的性能对比

 1  public class Monitor
 2     {
 3         int iValue = 12345;
 4         static long commonSeconds = 0; //普通方法运行时间
 5         static long objectSeconds = 0; //object方法运行时间
 6         static long genericSeconds = 0; //泛型方法运行时间
 7
 8         public static void ShowMonitor()
 9         {
10             {
11
12                 Stopwatch commonWatch = new Stopwatch();
13                 commonWatch.Start();
14                 for (int i = 0; i < 1000000000; i++)
15                 {
16                     commonMethod(i);
17                 }
18                 commonWatch.Stop();
19                 commonSeconds = commonWatch.ElapsedMilliseconds;
20             }
21
22             {
23
24                 Stopwatch objectWatch = new Stopwatch();
25                 objectWatch.Start();
26                 for (int i = 0; i < 1000000000; i++)
27                 {
28                     objectMethod(i);
29                 }
30                 objectWatch.Stop();
31                 objectSeconds = objectWatch.ElapsedMilliseconds;
32             }
33
34             {
35
36                 Stopwatch genericWatch = new Stopwatch();
37                 genericWatch.Start();
38                 for (int i = 0; i < 1000000000; i++)
39                 {
40                     genericMethod(i);
41                 }
42                 genericWatch.Stop();
43                 genericSeconds = genericWatch.ElapsedMilliseconds;
44             }
45             Console.WriteLine("普通方法的运行时间为:{0},object方法的运行时间为:{1},泛型方法的运行时间为:{2}",commonSeconds,objectSeconds,genericSeconds);
46         }
47
48
49         public static void commonMethod(int iValue) { }
50         public static void objectMethod(object objValue) { }
51
52         public static void genericMethod<T>(T tValue) { }
53     }

性能对比代码

代码中定义三个方法,分别为普通方法,object方法,泛型方法

依次进行十亿次的调用传递值类型参数进行函数调用,然后分别记录下执行时间。通过对比可以看出普通方法和泛型方法的执行时间相近。object方法执行时间几乎为前两者的2倍,这是装箱带来的副作用。

泛型方法在代码整洁度和维护成本上又超过了普通方法。泛型方法应该是同等需求下的最优之选。

泛型的应用,泛型方法,泛型类,泛型接口,泛型委托

 1   /// <summary>
 2     /// 泛型类  参考List<>
 3     /// 相当于在GenericClass类范围内声明了三个局部类型  A/B/C
 4     /// </summary>
 5     /// <typeparam name="A"></typeparam>
 6     /// <typeparam name="B"></typeparam>
 7     /// <typeparam name="C"></typeparam>
 8     public class GenericClass<A,B,C>
 9     {
10         public void Show(A a) {   //可以直接使用泛型类型
11
12         }
13     }
14
15     public interface iInterface<T> {
16         void Study(T t);
17         T Get(T t);
18     }
19
20     public delegate T ShowDelegate<T>(T t);

泛型方法,类,接口,委托

泛型约束

如果只是定义了一个泛型方法,不对传入的泛型类型参数做约束那么代码就不可控进而会出现不可预期bug。

泛型类型的约束有以下5类:无参数构造函数约束,引用类型约束,值类型约束,基类约束,接口约束。对应代码为(new(),class,struct,基类名,接口名)

以下代码展示以上各种约束。

 1  public interface iSports
 2     {
 3         void Play();
 4     }
 5     public class People
 6     {
 7         public int ID { get; set; }
 8         public string Name { get; set; }
 9
10         public virtual void Hi() {
11             Console.WriteLine("你好");
12         }
13     }
14
15     public class Chinese : People, iSports
16     {
17         public void Play()
18         {
19             Console.WriteLine("打乒乓球。");
20         }
21         public string tradition = "仁义礼智信,温良恭俭让";
22
23         public override void Hi()
24         {
25             Console.WriteLine("吃了没");
26         }
27     }
28
29     public class HuBei : Chinese {
30         public void Majiang() {
31             Console.WriteLine("打麻将");
32         }
33     }
34
35     public class Japanese : iSports
36     {
37         public int ID { get; set; }
38         public string Name { get; set; }
39         public void Play()
40         {
41             Console.WriteLine("打乒乓球");
42         }
43         public void Hi() {
44             Console.WriteLine("日本打招呼");
45         }
46     }

Model类用以继承和实现

 1 /// <summary>
 2     /// 泛型约束:积累约束/接口约束/引用类型约束/值类型约束/无参数构造函数约束(new())
 3     /// </summary>
 4    public class Constriant
 5     {
 6         public static void Show<T>(T tParameter) where T:People
 7         {
 8             Console.WriteLine("This is {0},parameter {1},type={2}",
 9                 typeof(CommonMethod).Name, tParameter, tParameter.GetType().Name);
10             Console.WriteLine(tParameter.ID);
11             Console.WriteLine(tParameter.Name);
12             tParameter.Hi();
13         }
14
15         /// <summary>
16         /// 接口约束,传递过来的类型参数必须实现了iSports接口
17         /// </summary>
18         /// <typeparam name="T"></typeparam>
19         /// <param name="tParameter"></param>
20         public static void ShowInterface<T>(T tParameter) where T:iSports
21         {
22             Console.WriteLine("This is {0},parameter {1},type={2}",
23                 typeof(CommonMethod).Name, tParameter, tParameter.GetType().Name);
24             tParameter.Play();
25         }
26
27         /// <summary>
28         /// 引用类型约束
29         /// </summary>
30         /// <typeparam name="T"></typeparam>
31         /// <returns></returns>
32         public static T Get<T>()
33             where T:class
34         {
35             return default(T);
36         }
37         /// <summary>
38         /// 值类型约束
39         /// </summary>
40         /// <typeparam name="T"></typeparam>
41         /// <returns></returns>
42         public static T GetStruct<T>()
43             where T : struct
44         {
45             return default(T);
46         }
47
48         public static T GetConstructor<T>()
49             where T:new() //无参数构造函数约束
50         {
51             T t = new T();
52             return default(T);
53         }
54     }

泛型类型约束

 1  Console.WriteLine("**************泛型约束:基类约束**************");
 2             People people = new People() {
 3                 ID = 1,
 4                 Name ="zhangsan"
 5             };
 6             Chinese chinese = new Chinese() {
 7                 ID = 2,
 8                 Name = "lisi"
 9             };
10             HuBei hubei = new HuBei() {
11                 ID=3,
12                 Name = "xl"
13             };
14             Constriant.Show(people);
15             Constriant.Show(chinese);
16             Constriant.Show(hubei);   //调用基类约束的泛型方法,传递的类型必须是基类或者子类
17
18             Japanese japanese = new Japanese() {
19                 ID = 4,
20                 Name ="小泉"
21             };
22             //Constriant.Show(japanese);//japanese 没有从people派生,不符合基类约束不能通过编译
23             Console.WriteLine("*********泛型约束:接口约束************");
24             //Constriant.ShowInterface(people);  people类没有实现iSport接口,不符合接口约束不能通过编译
25             Constriant.ShowInterface(chinese);
26             Constriant.ShowInterface(hubei);
27             Constriant.ShowInterface(japanese);  //japanese实现了iSport接口,可以编译通过

泛型约束调用

在泛型约束调用时可见,因为japanese没有从people类中派生,所以在调用有泛型类型People基类约束时候会报错,这样在编译时期就能避免类型不对应而导致的错误。

泛型的逆变,协变

泛型缓存

时间: 2024-11-04 17:51:26

1.net基础之泛型的相关文章

黑马程序员-基础加强-泛型

Java泛型(generics)是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换. 这种参数类型可以用在类.接口和方法的创建中,分别称为泛型类.泛型接口.泛型方法. Java语言引入泛型的好处是安全简单. 在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的"任意化","任意化"带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者

java基础之泛型用法

1.什么是泛型 泛型是java中保障类型安全的一种机制.它通过对变量类型的假设,实现变量类型的进行限制,从而在一定程度上保证程序编译时变量类型的安全.反之,如果没有泛型,这些假设则只存在于程序员的大脑中,这样会导致类型转换的异常在程序运行时才被发现. //不用泛型 List list1 = new ArrayList(); list1.add(1); Object o = list1.get(0); //返回Object类型对象 Integer i = (Integer) o; //需预先知道类

[.net 面向对象编程基础] (18) 泛型

[.net 面向对象编程基础] (18) 泛型 上一节我们说到了两种数据类型数组和集合,数组是指包含同一类型的多个元素,集合是指.net中提供数据存储和检索的专用类. 数组使用前需要先指定大小,并且检索不方便.集合检索和声明方便,但是存在类型安全问题,本来使一个类型安全的C#变得不安全了. 集合为了解决数组预设大小的问题,采取了一种自动扩容的办法,这样当大小不够时,他就创建一个新的存储区域,把原有集合的元素复制过来.如此又对性能上也是有很大的影响. 上节我们说到解决这些缺陷的方法,那就是.NET

Java基础:泛型

Java的泛型是什么呢, 就是类型的参数化,这得类型包括方法参数和返回值,也就是原本该是确定类型的地方换成了变量,把类型的确定时间向后延迟了. 在之前,学过"重载"的概念,重载是什么呢,举例来说 public class Test{ // 处理整型数据 void receive(int i) { System.out.println("Received one int data"); System.out.println("i="+i); } /

Java基础巩固----泛型

注:参考书籍:Java语言程序设计.本篇文章为读书笔记,供大家参考学习使用   1.使用泛型的主要优点是能够在编译时而不是在运行时检查出错误,提高了代码的安全性和可读性,同时也提高了代码的复用性. 1.1如何理解泛型的使用提高了代码的安全性? 答:例如这样一段代码: ArrayList<Date> arrayList = new ArrayList<Date>(); arrayList.add(new Date()); arrayList.add("data")

java基础之泛型的继承

关于泛型的基本介绍和理解请参考以下几篇文章,或查询更多资料: 泛?型?与?泛?型?继?承 泛型(包括泛型抽象类的继承) 泛型的继承测试 本篇以简单的List<>方式来进行说明. ArrayList<Object>继承了List<Object>, ArrayList<String>没有继承List<Object> List<?>等价于List<? extends Object> 请参考以下代码: /** * author D

框架学习前基础加强 泛型,注解,反射(泛型&注解)应用案例,IOC,Servlet3.0,动态代理,类加载器

泛型 1. 泛型类 :具有一个或多个类型变量的类,称之为泛型类! class A<T> { } 2. 在创建泛型类实例时,需要为其类型变量赋值 A<String> a = new A<String>(); * 如果创建实例时,不给类型变量赋值,那么会有一个警告! 3. 泛型方法 :具有一个或多个类型变量的方法,称之为泛型方法! class A<T> { public T fun(T t1) {} } fun()方法不是泛型方法!它是泛型类中的一个方法! pu

JAVA基础_泛型

什么是泛型 泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时会去除掉"类型"信息,是程序的运行效率不受影响,对于参数化的泛型类型,getClass()方法返回值和原始类型完全一样.由于编译生成的字节码会擦除泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,然后再调用add()方法即可 GenericDemo.java public class GenericDemo

Java基础学习——泛型

一.泛型方法 1 /** 2 3 自定义泛型:自定义泛型可以理解为是一个数据类型的占位符,或者理解为是一个数据类型的变量. 4 5 泛型方法: 6 泛型方法的自定义格式:修饰符<声明自定义泛型>返回值类型 函数名称(形参列表) 7 在自定义泛型方法上泛型的具体类型是调用该方法的时候传入参数的类型所确定的 8 9 */ 10 public class demo1 { 11 public <T>T printf (T t){ 12 return t; 13 } 14 public st

Java基础加强——泛型

一.泛型的几个术语: 对于List<User> 和List<T> 整个List<T>   泛型类型 List<T>中的T   类型参数 整个List<User>    参数化类型 List<User>中的User   实际类型参数 <> 为   typeof 注意的地方: 参数化类型没有实际类型参数的继承关系! List<Integer> list = new List<Object>(); //报