C#进阶之泛型(Generic)

1、泛型

泛型是framwork2.0推出的新语法,具有延迟声明的特点:把参数类型的声明推迟到调用的时候。泛型不是一个语法糖,是框架升级提供的功能。需要编辑器和JIT(just-in-time compilation、即时编译)的支持。

泛型并不存在性能问题,因为编译器支持 ,在即时编译的时候,编译器会生成一个泛型方法的副本,基本上和固定类型的方法性能无差别。

泛型的用处就是 用一个类、方法、接口、委托来满足不同的具体类型,然后做一样的事情。

泛型的约束有以下几种类型:

  1. 基类约束
  2. 接口约束
  3. 引用类型约束
  4. 值类型约束
  5. 无参数构造函数约束

约束必须是接口、非密封类(密封类无法被继承,不存在子类,所以约束没有意义)、类型参数;

约束可叠加,

泛型约束主要是用来保证代码安全。

2、协变逆变

这里用代码来解释一下这两个概念

 1 using System;
 2 using System.Collections.Generic;
 3
 4 namespace Util_YCH.Build.泛型
 5 {
 6     /// <summary>
 7     /// 协变实例
 8     /// </summary>
 9     /// <typeparam name="T"></typeparam>
10     public interface IListAnimals<out T> {
11         /// <summary>
12         /// T只能作为返回值不能作为入参
13         /// </summary>
14         /// <returns></returns>
15         T GetT();
16         /// <summary>
17         /// 所以这里会编译报错
18         /// </summary>
19         /// <param name="t"></param>
20         void setT(T t);
21     }
22     public class ListAnimals<T> : IListAnimals<T>
23     {
24         T t;
25         public T GetT()
26         {
27             throw new NotImplementedException();
28         }
29
30         public void setT(T t)
31         { }
32     }
33     /// <summary>
34     /// 逆变实例
35     /// </summary>
36     /// <typeparam name="T"></typeparam>
37     public interface IListDogs<in T>
38     {
39         /// <summary>
40         /// T只能作为入参不能作为返回值
41         /// </summary>
42         /// <param name="t"></param>
43         void setT(T t);
44         /// <summary>
45         /// T无法作为返回值,此处会编译报错
46         /// </summary>
47         /// <returns></returns>
48         T GetT();
49
50     }
51     public class ListDogs<T> : IListDogs<T>
52     {
53         public T GetT()
54         {
55             throw new NotImplementedException();
56         }
57
58         public void setT(T t)
59         {
60             throw new NotImplementedException();
61         }
62     }
63     /// <summary>
64     /// 动物类
65     /// </summary>
66     public class Animal
67     {
68     }
69     /// <summary>
70     /// 狗类
71     /// </summary>
72     public class Dog : Animal
73     {
74     }
75
76     public class Test {
77         public Test(){
78
79             Animal animal1 = new Animal();
80             Dog dog = new Dog();
81             Animal animal2 = new Dog();//狗是动物
82             List<Animal> animals = new List<Dog>();
83             //按照常规而言,Dog是Animal的子类,这样写应该是没有问题的,凡是编译器报错,
84             //原因是因为Dog是Animal的子类,但是List<Dog> 与 List<Animal> 之间不存在继承关系,
85             //于是为了消除这个BUG,就有了【协变】的概念
86             #region 协变
87             IListAnimals<Animal> listAnimals = new ListAnimals<Dog>();
88             #endregion
89             #region 逆变
90             IListDogs<Dog> listAnimals2 = new ListDogs<Animal>();
91             #endregion
92         }
93
94     }
95 }

3、泛型缓存

由于CLR会针对不同的类型会生成一个副本,所以可以实现泛型的缓存,示例代码如下

 1 using System;
 2
 3 namespace Util_YCH.Build.泛型
 4 {
 5     /// <summary>
 6     /// 每个不同的类型T都会生成一个副本,
 7     /// 根据C#语言特性,静态字段和方法会在程序第一次运行的时候执行,缓存效率远远高于字典等缓存。
 8     /// </summary>
 9     public class Cache<T>
10     {
11         public Cache()
12         {
13             CacheStr = DateTime.Now.ToString();
14         }
15         private static string CacheStr = "";
16         public static string GetCacheStr() {
17             return CacheStr;
18         }
19     }
20
21     public class Test {
22         public Test(){
23
24             #region 泛型缓存
25             var cache1 = new Cache<int>();
26             var cache2 = new Cache<string>();
27             var cache3 = new Cache<DateTime>();
28             var cache4 = new Cache<double>();
29             var cache5 = new Cache<bool>();
30             #endregion
31
32             var cache11 = Cache<int>.GetCacheStr();
33             var cache12 = Cache<int>.GetCacheStr();
34             Console.WriteLine(cache11 == cache12);
35             Console.ReadKey();
36         }
37
38     }
39 }

字典缓存是哈希结构的,读取缓存的时候需要进行查找,会消耗一定的资源;而泛型缓存的副本存在于内存里面,查找起来速度极快,但是有局限性,就是和类型相关,具有一定的限制。

这里的应用场景我能想到的就是可以针对每个实体缓存CRUD的Sql语句。

原文地址:https://www.cnblogs.com/yuchenghao/p/12089288.html

时间: 2024-11-10 07:05:55

C#进阶之泛型(Generic)的相关文章

Java基础之Comparable接口, Collections类,Iterator接口,泛型(Generic)

一.Comparable接口, Collections类 List的常用算法: sort(List); 排序,如果需要对自定义的类进行排序, 那就必须要让其实现Comparable接口, 实现比较两个类大小的方法 shuffle(List); 随机排列 void reverse(List); 逆序排列(Linked效率较高) copy(); 复制集合, 前提是size()相同(长度, 和容量的区别) fill(List, Object);使用某个对象填充整个List binarySearch()

JAVA学习笔记(五十六)- 泛型 Generic Types

泛型 Generic Types import java.util.ArrayList; import java.util.List; /* * 泛型 Generic Types * 集合泛型 * 类泛型 * 方法泛型 */ public class Test01 { public static void main(String[] args) { // 1.集合泛型,保证集合中元素的类型安全 List<Integer> nums = new ArrayList<Integer>(

Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口

Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器内的元素的遍历 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为"轻量级"对象,因为创建它的代价小. Java中的Iterator功能比较简单,并且只能单向移动: (1) 使用方法iterator()要求容器返回一个I

C#泛型(Generic)

一.什么是泛型 泛型(Generic)是C#语言2.0.通用语言运行时(CLR)2.0..NET Framework2.0推出来的新特性. 泛型为.NET框架引入类型参数(Type Parameters)的概念.类型参数使得设计类和方法时,不必确定一个或多个参具体数. 具体的参数类型可延迟到声明和使用时再确定.避免了运行时类型转换或装箱操作的代价和风险. 二.泛型的使用和对比 2.1.CommandMethod(普通方法) 1 /// <summary> 2 /// 打印一个Int值 3 //

泛型 Generic 类型擦除引起的问题及解决方法

参考:http://blog.csdn.net/lonelyroamer/article/details/7868820#comments 因为种种原因,Java不能实现真正的泛型,只能使用类型擦除来实现伪泛型,这样虽然不会有类型膨胀的问题,但是也引起了许多新的问题.所以,Sun对这些问题作出了许多限制,避免我们犯各种错误. 1.先检查,再编译,以及检查编译的对象和引用传递的问题 既然说类型变量会在编译的时候擦除掉,那为什么我们往ArrayList<String> arrayList=new

java 泛型(Generic)

java泛型(generic) 2016-07-11 问题 向集合存储元素存在安全性问题,即很可能不知道已有的集合中已经存储的元素的类型是什么,这时就不应该向该集合随便添加元素,否则与集合的设计的初衷相悖,因为集合存储的是同类型的元素,而且以后取集合中的元素不知道该转为什么类型. 从集合中获取元素需要强制类型转换,可能出现ClassCastException问题 未使用泛型举例: 说明:任何Object子类均可以存入Object集合,但是从集合中获取元素,则是Object对象,需要强制转换,可能

泛型(Generic)

1.定义:一种特殊的变量,保存的是引用变量的类型 2.好处:避免数据类型的转换;将运行时期ClassCastException提前到编译时期 3.自定义带泛型的类:     public class A<泛型名>{ }     注:类中凡是使用到数据类型的地方,都可以使用泛型名代替;         泛型名自定义,但是将来使用者只能传递引用数据类型; 1 代码实现: 2 //自定义泛型类和泛型方法: 3 class A<MM>{ 4 private MM name; 5 priva

1、(知识篇)泛型Generic

泛型的使用: public class Test { public static void main(String[] args) { DoWork<Person> doWork = new DoWork<>(); doWork.doSth(new Person()); DoEat<Man> doEat = new DoEat<>(); doEat.doSth(new Man()); } // 普通类 public static class Person {

Java泛型Generic - Thinking in Java读书笔记

1.什么是泛型? 泛型就是可适用于很多的类,它实现了参数化类型type parameter的概念,参数化类型指可使用多种类型. 多态是一种泛化机制. 例如方法 A(Base b){}//Base是一个基类 这样方法A就可以接受从这个基类Base的任何子类作为参数.方法的参数也可以是一个接口,但是由于类的单继承体系和接口的约束( An interface still requires that your code works with that particular interface. ),不能