.NET泛型解析(下)
上一篇对.NET中的泛型进行了详细的介绍以及使用泛型的好处是什么,这篇将更加深入的去了解泛型的其他的知识点,重头戏.
【1】泛型方法
1 public class GenericType<T> 2 { 3 4 private T G_Value; 5 6 public T Convert<T> { T res = (T)Convert.ChangeType(G_value,typeof(T)); return res; } 7 8 }
1 static void Test<T >(ref T t1,ref T t2) 2 { 3 T temp = t1; 4 t1 = t2; 5 t2 = temp; 6 }
这是我们定义的一个泛型方法,第一个参数类型为 T,第二个也为 T,说明这两个类型是一致的。那么我们在调用的时候应该这样 :
1 int i = 8, j = 0 ; 2 3 Test( ref i, ref j);
而如果我们两个实参的类型不统一的话,那么就会引发编译异常例如 :
开放类型和封闭类型
1 class DictionaryStringKey <T> : IEnumerable<T> 2 { 3 public IEnumerator<T> GetEnumerator() 4 { 5 throw new NotImplementedException(); 6 } 7 8 System .Collections. IEnumerator System. Collections.IEnumerable .GetEnumerator() 9 { 10 throw new NotImplementedException(); 11 } 12 }
View Code
在上述代码中,有一个DictionaryStringKey的类,继承了一个IEnumable<T>的泛型,那么根据我们的开放类型它在调用的时候是不只是具体的实参,并且不能被构造实例的.
1 static void Main( string[] args) 2 { 3 object o = null; 4 Type t = typeof( DictionaryStringKey <>); 5 o = CreateInstance(t); 6 Console .ReadLine(); 7 8 } 9 10 private static object CreateInstance( Type t) 11 { 12 object o = null; 13 try 14 { 15 o = Activator . CreateInstance(t); 16 Console .WriteLine( @" 创建了 " + t + "的实例 " , t .ToString()); 17 } 18 catch (Exception ex) 19 { 20 o = Activator . CreateInstance(t); 21 Console .WriteLine( @" 创建 " + t + "的实例失败 " , t .ToString()); 22 } 23 24 return o; 25 }
View Code
上述代码中我尝试着对开放类型进行实例化,结果报出异常 :
当我们传入实参之后,那么它就是一个封闭类型,这样我们就可以进行构造实例了.
1 static void Main( string[] args) 2 { 3 object o = null; 4 Type t = typeof( DictionaryStringKey <string > ); 5 o = CreateInstance(t); 6 Console .ReadLine(); 7 8 }
View Code
【2】泛型接口
泛型的主要作用就是定义泛型的引用类型和值类型,在CLR中,对于泛型接口的支持也是很重要的,因为这样更有益与程序的扩展性, 另外一点如果没有泛型接口我们每次使用非泛型接口时都会进行装箱操作(例如: IComparable),并且会失去编译时的安全性(因为它是非泛型的,较之泛型的好处之一).
那么CLR提供了对于泛型接口的支持,对于引用类型和值类型可以通过制定实参的方式来实现泛型接口,同时也可以保持未指定状态来实现一个泛型接口( 接受者也可以是泛型 , 可以在后期进行指定类型)
实例 1 : 声明一个泛型接口
1 interface IPair <T> 2 { 3 T First { get; set ; } 4 T Second { get; set ; } 5 }
1 class Pair <T> : IPiar< T> 2 { 3 public T First 4 { 5 get 6 { 7 throw new NotImplementedException(); 8 } 9 set 10 { 11 throw new NotImplementedException(); 12 } 13 } 14 15 public T Second 16 { 17 get 18 { 19 throw new NotImplementedException(); 20 } 21 set 22 { 23 throw new NotImplementedException(); 24 } 25 } 26 }
View Code
CLR泛型接口的支持对于集合类型来讲尤其重要,同时泛型在集合类型中较为常用,如果没有泛型那么我们所使用List的时候都要依赖与System.Collections,我们在每次访问的时候都需要执行一次转换,如果使用泛型接口,就可以避免执行转型,因为参数化的接口能实现更强的编译时绑定.
实例 3 : 在一个类中多次实现相同的接口
1 interface IContainer <T> 2 { 3 ICollection<T > Items { get ; set; } 4 } 5 6 public class Person : IContainer<A >,IContainer <B> 7 { 8 9 public ICollection <A> Items 10 { 11 get 12 { 13 throw new NotImplementedException(); 14 } 15 set 16 { 17 throw new NotImplementedException(); 18 } 19 } 20 21 ICollection<B > IContainer <B>. Items 22 { 23 get 24 { 25 throw new NotImplementedException(); 26 } 27 set 28 { 29 throw new NotImplementedException(); 30 } 31 } 32 }
View Code
Items属性使用一个显式接口实现多次出现,每一次,类型参数都有所不同,如果没有泛型,这是做不到的,在非泛型的情况下,CLR只允许一个显式的IContainer.Items属性.
【4】泛型约束(主要约束,次要约束,构造器约束)
约束也可以理解为是一种规则,意思就是我们所编写的所有泛型,你在调用的时候,应该给我传输那些类型的实参。
1 struct Generic<T>(T t1) where : class
1 class ConstraintOfStruct <T> where T : struct 2 { 3 public T result() 4 { 5 return new T(); 6 } 7 }
在代码中,我们最后返回的是new T(),这个是没有问题的,因为我们已经可以肯定T就是值类型,所有的值类型都有一个隐式的构造函数,那么如果我们将 约束条件改为 class的话,那么就会出异常,因为不是所有的引用类型都可以实例化.
实例 6 : 反面教材 - 约束为引用类型时进行实例化.
1 public T CreateInatance<T >() where T : new() 2 { 3 return new T(); 4 }
在方法createInstance中,要求我们必须传入一个无参的构造函数,例如:我们可以传入 object,struct,stream等,但是不能传入 string,Directory等.
接口约束:
1 class ConstraintOfStruct <T> where T : class,IEquatable <T> ,IComparable<T> 2 { 3 }
1 class Sample<T> where T : class ,IDisposable,new(){} 2 class Sample<T> where T : struct,IDisposable{} 3 class Sample<T,U> where T : Stream where U : IDisposable{} 4 5 class Sample<T> where T : class ,struct
View Code
【5】泛型类型转型
1 public static T Desercialies <T > (Stream stream, IFormatter formatter) 2 { 3 return (T)formatter. Deserialize(stream); 4 }
formatter 负责将流转换为 Object,返回一个Object类型,我们在使用泛型调用的时候应该这样来 :
1 string result = Desercialies <string > (stream, formatter);
上述的代码看着是一种强制转换,但是仍然执行了隐式的转换,就和使用非泛型 string result = (string)Desercialies(stream, formatter); 一样
【6】泛型和属性
属性也可以应用到泛型类型中,使用的方式和非泛型类型相同.自定义的属性只允许引用开发泛型类型
1 class MyClass<T,S> where T :class 2 where S : struct 3 { 4 public T MyName { get; set; } 5 public S MyCode { get; set; } 6 public List<T> MyCourse { get; set; } 7 public List<S> MyStudyHistory { get; set; } 8 }
上述我们定义了一个MyClass 类,这个类有两个参数一个是引用类型一个是值类型.在属性MyName,MyCourse的类型都是引用类型,MyCode的类型都为值类型
泛型类型构造器:
1 class Pair < T> : IPiar< T > 2 { 3 private T _first; 4 5 public T First 6 { 7 get { return _first; } 8 set { _first = value; } 9 } 10 private T _second; 11 12 public T Second 13 { 14 get { return _second; } 15 set { _second = value; } 16 } 17 public Pair(T first,T second) 18 { 19 20 } 21 } 22 interface IPiar < T> { }
View Code
泛型的构造器不需要添加类型参数来与类的声明一致.
先到这里, 下一篇着重分享协变和逆变,否则这一篇符太长,不利于以后的查看.
泛型委托和泛型反射留在深入总结委托和反射的时候进行总结。
同时,希望给在阅读的你带来一些帮助。
转载于:https://www.cnblogs.com/DeepLearing/p/4564791.html
.NET泛型解析(下)相关推荐
- Java泛型解析(02):通配符限定
Java泛型解析(02):通配符限定 考虑一个这种场景.计算数组中的最大元素. [code01] public class ArrayUtil {public static <T> ...
- Retrofit 泛型解析遇到com.google.gson.internal.LinkedTreeMap cannot be cast to object
在Retrofit网络请求数据,使用泛型解析json时,出现了com.google.gson.internal.LinkedTreeMap cannot be cast to com.xylife.c ...
- 《重学Java系列》之 泛型(下)
不诗意的女程序媛不是好厨师~ 转载请注明出处,From李诗雨-https://blog.csdn.net/cjm2484836553/article/details/103302194] 在 < ...
- Laravel5.2之Filesystem源码解析(下)
2019独角兽企业重金招聘Python工程师标准>>> 说明:本文主要学习下\League\Flysystem这个Filesystem Abstract Layer,学习下这个pac ...
- Android之EventBus框架源码解析下(源码解析)
转载请标明出处:[顾林海的博客] 个人开发的微信小程序,目前功能是书籍推荐,后续会完善一些新功能,希望大家多多支持! 前言 EventBus是典型的发布订阅模式,多个订阅者可以订阅某个事件,发布者通过 ...
- Kotlin的解析(下)
前言 通过上章节的学习,了解到了枚举类,数据类,封闭类,泛型,扩展,对于一些使用的语法糖有了一定的认识,接下来让我们一起更加深入的了解一下更加晦涩的Kotline 1. 对象和委托 1.1 对象( ...
- .NET泛型解析(上)
[1]:泛型介绍 泛型是C#2.0中一个重要的新特性,泛型是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用.泛型通常用与集合以及作用于集合的方法一起使用,当然也可以单独使用. C#是一 ...
- AndFix解析——(下)
我们接着分析阿里开源的AndFix库, 上一篇分析了Patch类,这个类相当于我们提供补丁的容器,容器里有了东西,我们要对容器进行操作了, 于是开始了我们这次的分析. 在第二篇里,我们添了Patch类 ...
- Android/Java中使用Protobuf的Any类型实现泛型解析
上一篇博客中只讲解到了简单的使用protobuf,还不会的可以先去看一下[Android项目使用Protobuf教程(结合Retrofit+RxJava及HttpURLConnection使用)],有 ...
最新文章
- Eclipse GCC 入门
- linux远程工具_【linux实操3.1】linux远程连接工具Secure的使用
- 数据结构实验之栈八:栈的基本操作
- 如何在python中获取浮点数的十六进制值?
- [Django学习] Django基础(5)_优化分页器
- portainer安装_Docker 图形化工具—Portainer
- MS CRM 2011的自定义与开发(2)——预备知识
- PhoneGap在Microsoft Visual Studio Express For Wi...
- 芯烨网口小票打印机,使用PHP打印小票
- 模电学习笔记(上交郑老师)2.二极管
- 如何看待爱迪生和特斯拉的直流交流电之争——两种模式的企业管理
- python中output使用_Python使用input() output()函数输入、输出数据记录
- 戴尔 R730xd 服务器更改管理口密码 图文教程
- Python正则表达式-re模块奇技淫巧
- LeetCode:974. Subarray Sums Divisible by K - Python
- Linux 中power supply软件架构和相关API
- RSA非对称加密和解密(同时生成密钥)
- JNI和NKD入门系列三,在android studio上设置javah和ndk-build的快捷键
- 模拟器,预览,自动预览,自动真机调试有用,扫二维码真机调试报错
- 查看表所有列名SQL
热门文章
- 考研规划计算机科学与技术,【图片】2020考研,老学长教你如何规划!【计算机考研吧】_百度贴吧...
- 有趣的计算机课的作文,有趣的电脑课作文500字
- linux 启动脚本sleep后不执行_JMeter多脚本间的启动延时
- animation动画不生效_关于CSS3的animation使用的一些坑,需要注意下!
- 数字图像处理:(1)图像梯度以及算子应用
- 霍夫变换(Hough Transform):霍夫变化在图像处理以及点云处理中的直线检测应用
- STM32F103C8/BT6最小系统原理图、PCB
- GitHub开源游戏:CityBound(模拟城市)
- 【camera】基于深度学习的车牌检测与识别系统实现(课程设计)
- 温控自动烘焙系统的研究与实现