[译]聊聊C#中的泛型的使用
写在前面
今天忙里偷闲在浏览外文的时候看到一篇讲C#中泛型的使用的文章,因此加上本人的理解以及四级没过的英语水平斗胆给大伙进行了翻译,当然在翻译的过程中发现了一些问题,因此也进行了纠正,当然,原文的地址我放在最下面,如果你的英文水平比较好的话,可以直接直接阅读全文。同时最近建了一个.NET Core实战项目交流群637326624,有兴趣的朋友可以来相互交流。目前.NET Core实战项目之CMS的教程也已经更新了6篇了,目前两到三天更新一篇。
作者:依乐祝
原文地址:https://www.cnblogs.com/yilezhu/p/10029782.html
介绍
C#和.NET中的泛型程序具有强类型集合的许多优点,并为代码提供更高质量和性能提升。泛型是C#语言和公共语言运行库(CLR)中的一个新功能,它将类型参数的概念引入.NET Framework。类型参数使得设计某些类和方法成为可能,例如,通过使用泛型类型参数T,可以大大简化类型之间的强制转换或装箱操作的过程(装箱、拆箱问题)。说白了,泛型就是通过参数化类型来实现在同一份代码上操作多种数据类型,利用“参数化类型”将类型抽象化,从而实现灵活的复用。每个集合的详细规范可以在System.Collection.Generic名称空间下找到。
装箱和拆箱
.Net定义了两种主要的数据类型来表示变量,也就是传说中的值类型和引用类型。这是需要装箱和拆箱的地方。装箱是一种通过将变量存储到System.Object中来显式地将值类型转换为引用类型的机制。当您装入值时,CLR会将新对象分配到堆中,并将值类型的值复制到该实例中。例如,您创建了一个int类型的变量:
int a = 20; object b = a; //装箱
相反的操作是拆箱,它是将引用类型转换回值类型的过程。此过程验证接收数据类型是否与装箱类型一致;
int c = (int)b; // 拆箱
C#编译器可以看到从int到object的赋值,反之亦然。当编译该程序并通过IL解析器检查IL生成的代码时,您会注意到当b被赋值为a时,程序通过在IL中自动插入一个box指令来响应,当c被赋值为b时如下;
代码加载常量20并将其存储在本地插槽中;它将值20加载到堆栈中并将其装箱。最后,它将被装箱的20返回到堆栈上,并将其拆箱为int类型
这个过程.NET CLR执行了一系列操作,例如,首先在托管堆中分配一个对象,然后在装箱中将值转换为内存位置,并在拆箱期间将值存储在堆上并且必须转回到堆栈。因此,从性能的角度来看,装箱和拆箱过程在泛型中具有非常重要的意义,因为这个过程如果不使用泛型的话会耗费更多地资源。
泛型类
可以通过在类名后面加上符号来定义泛型类。这里没有强制必须将“T”字放在泛型的定义中。您可以在TestClass <>类声明中使用任何单词。
public class TestClass<T> { }
System.Collection.Generic命名空间下还定义了许多实现了这些关键字接口的类型。下表列出了此命名空间的核心类类型。
泛型类 | 描述 |
---|---|
Collection | 泛型集合的基类,可以比较两个泛型对象是否相等 |
Dictionary<TKey, TValue> | 键值对的泛型集合 |
List | 可动态调整列表项的大小 |
Queue | 先进先出(FIFO)列表的泛型实现 |
Stack | 后进先出(LIFO)列表的泛型实现 |
简单的泛型类示例
以下示例显示了一个简单的泛型类型的操作。TestClass 定义一个长度为5的泛型类型数组。Add()方法负责将任何类型的对象添加到集合中,而Indexer属性是循环
在构建并运行该程序之后,程序的输出如下所示;
泛型的主要特性
泛型类型的一些重要特征使它们相比传统的非泛型类型具有如下的显著特征:
类型安全
性能
二进制代码复用
类型安全
泛型最重要的特征之一是类型安全性。对于非泛型ArrayList类,如果使用对象类型,则可以向集合中添加任何类型,这些类型有时会导致严重的问题。下面的示例显示向ArrayList类型的集合添加一个整数、字符串和对象;
ArrayList obj = new ArrayList();
obj.Add(50);
obj.Add("Dog");
obj.Add(new TestClass());
现在,如果使用整数对象来使用foreach语句进行遍历的话,当编译器接受到代码,但是因为集合中的所有元素都不是整数,所以会导致运行时异常;
foreach(int i in obj)
{ Console.WriteLine(i);
}
编程的经验法则是应该尽早检测到错误。对于泛型类Test,泛型类型T定义允许哪些类型。通过使用Test的定义,只能向集合添加整型类型的数据。这时候当Add()方法具有以下无效参数的时候编译器将不编译代码;
Test<int> obj = new Test<int>();
obj.Add(50);
obj.Add("Dog"); //编译错误 obj.Add(new TestClass()); //编译错误
性能
在下面的示例中,ArrayList类存储对象,并且定义了Add()方法来存储一些整型参数。因此,整数类型被装箱。当使用foreach语句读取ArrayList中的值时,将发生拆箱。
ArrayList obj = new ArrayList();
obj.Add(50); //装箱- 值类型转换成引用类型 int x= (int)obj[0]; //拆箱foreach(int i in obj)
{ Console.WriteLine(i); // 拆箱}
注意:泛型比其他集合(如ArrayList)更快。
代替使用对象类型,TestClass类的泛型类型被定义为int,因此在从编译器动态生成的类中将使用int类型。所以将不会发生装箱和拆箱,如下所示;
TestClass<int> obj = new TestClass<int>();
obj.Add(50); //没有装箱 int x= obj[0]; // 没有拆箱foreach(int i in obj)
{ Console.WriteLine(i); //没有拆箱 }
二进制代码复用
泛型类型提供了一种源代码保护机制。泛型类可以定义一次,并且可以使用许多不同类型来进行实例化。泛型可以在一种CLR支持的语言中定义,并可以被另一种.NET语言使用。以下TestClass 使用int和string类型进行实例化:
TestClass<int> obj = new TestClass<int>();
obj.Add(50); TestClass<string> obj1 = new TestClass<string>();
Obj1.Add("hello");
通用方法
虽然大多数开发人员通常会使用基类库中的现有泛型类型,但也有可能会构建自己的泛型成员和自定义的泛型类型。
本示例的目的是构建一个交换方法,该方法可以使用单个类型参数对任何可能的数据类型(基于值或基于引用)进行操作。由于交换算法的性质,传入的参数将作为使用ref关键字修饰的引用类型来进行发送。
编译此泛型方法实现的程序后,输出如下所示;
字典
字典也被称为映射或散列表。它表示允许您基于关键字来访问元素的数据结构。字典的一个重要特征是更快的查找; 您可以添加或删除选项而不会产生性能开销。
.Net提供了几个字典类,例如Dictionary <TKey,TValue>。类型参数TKey和TValue分别表示关键字的类型和它可以存储的值。
简单的字典示例
以下示例演示使用泛型的简单字典集合。在此程序中,将创建一个Dictionary类型对象,该对象接受int作为键,字符串作为值。然后我们将一些字符串值添加到字典集合中,最后显示字典集合元素。
以下示例通过定义附加类emp来描述一些更复杂的问题,其中我们覆盖ToString()方法以显示特定员工的名称和薪水。稍后在Main()方法中,创建一个新的Dictionary <TKey,TValue)的实例,其中键的类型为string,值为emp类型。构造函数分配2个元素的容量。emp对象和作为键的字符串值被添加到字典集合中。最后,使用foreach语句迭代集合元素并显示在屏幕上。
队列
队列是一种特殊类型的容器,可确保以FIFO(先进先出)方式访问元素。队列集合最适合实现消息传递的组件。我们可以使用以下语法定义Queue集合对象:
Queue qObj = new Queue();
Queue集合的属性,方法和其他规则定义都位于Sysyem.Collection命名空间下。下表定义了关键成员;
System.Collection.Queue成员 | 定义 |
---|---|
Enqueue() | 将对象添加到队列的末尾。 |
Dequeue() | 从队列的开头删除对象。 |
Peek() | 返回队列开头的对象而不删除它。 |
下面演示了一个基本的队列类型的集合,将一些字符串类型值添加到集合中,最后使用while语句来显示整个集合中的数据 。
堆栈
Stack集合是LIFO的抽象(后进先出)。我们可以使用以下语法定义Stack集合对象:
Stack qObj = new Stack();
下表说明了堆栈的关键成员;
System.Collection.Stack成员 | 定义 |
---|---|
Contains() | 如果在集合中找到特定元素,则返回true。 |
Clear() | 删除集合的所有元素。 |
Peek() | 预览堆栈中的最新元素。 |
Push() | 它将元素推入堆栈。 |
Pop() | 返回并删除堆栈的顶部元素。 |
以下演示了堆栈集合。首先,将数组类型对象引用到堆栈集合中。然后使用Pop()方法从堆栈中删除集合中元素的值并显示在屏幕上。
在使用泛型实现的另一个示例中,使用Push()方法将5个项添加到堆栈中。然后使用循环迭代输出堆栈中的数据。堆栈的枚举器不会删除数据; 它只是以LIFO方式返回每个项目,如下所示:
总结
今天忙里偷闲,在浏览外文的时候看到一篇讲泛型的文章,因此就加上自己的理解进行了相关翻译,也加深了自己对泛型的理解!如果英文比较好的话可以直接访问https://www.c-sharpcorner.com/UploadFile/84c85b/using-generics-with-C-Sharp/ 自行查看!当然,我在翻译的过程中也发现了文中的一些错误,所以进行了更正!同时最近建了一个.NET Core实战项目交流群637326624,有兴趣的朋友可以来相互交流。目前.NET Core实战项目之CMS的教程也已经更新了6篇了,目前两到三天更新一篇。最后感谢大家的阅读。
原文地址:https://www.cnblogs.com/yilezhu/p/10029782.html
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com
[译]聊聊C#中的泛型的使用相关推荐
- 聊聊Java中的泛型
聊聊Java中的泛型 文章目录 聊聊Java中的泛型 参考资料 一.概述 1. 泛型的定义 1.1 定义 1.2 常见形式 2. 为什么需要泛型 3. 泛型的优点 4. 泛型的使用 4.1 泛型类 4 ...
- java定义list_我的Java Web之路59 - Java中的泛型
本系列文章旨在记录和总结自己在Java Web开发之路上的知识点.经验.问题和思考,希望能帮助更多(Java)码农和想成为(Java)码农的人. 目录 介绍 再谈Java中的类型 为什么需要泛型? J ...
- Java中创建泛型数组
Java中创建泛型数组 使用泛型时,我想很多人肯定尝试过如下的代码,去创建一个泛型数组 T[] array = new T[]; 当我们写出这样的代码时编译器会报Cannot create a gen ...
- 技术图文:C#语言中的泛型 II
C#语言中的泛型 II 知识结构: 6. 泛型接口 泛型类与泛型接口结合使用是很好的编程习惯,比如用IComparable<T>而非IComparable,以避免值类型上的装箱和拆箱操作. ...
- 技术图文:C#语言中的泛型 I
C#语言中的泛型 I 知识结构: 1. 泛型概述 泛型广泛应用于容器(Collections)和对容器操作的方法中. 从 .NET Framework2.0 开始,微软提供了一个新的命名空间Syste ...
- Java中的泛型 --- Java 编程思想
前言 我一直都认为泛型是程序语言设计中一个非常基础,重要的概念,Java 中的泛型到底是怎么样的,为什么会有泛型,泛型怎么发展出来的.通透理解泛型是学好基础里面中非常重要的.于是,我对<Ja ...
- 聊聊 Linux 中的五种 IO 模型
聊聊 Linux 中的五种 IO 模型 2016/04/21 · IT技术 · 8 评论 · iO, 同步, 异步, 阻塞, 非阻塞 分享到:0 本文作者: 伯乐在线 - 陶邦仁 .未经作者许可,禁止 ...
- [译] 探究 Swift 中的 Futures Promises
本文讲的是[译] 探究 Swift 中的 Futures & Promises, 原文地址:Under the hood of Futures & Promises in Swift ...
- 5.在MVC中使用泛型仓储模式和工作单元来进行增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...
最新文章
- 从数仓到数据中台,谈技术选型最优解
- 用Leangoo管理你的项目
- zabbix添加自定义监控项目-配置邮件告警-测试告警
- mysql 修改上传文件大小限制吗_修改PHP上传文件大小限制的方法(转)
- 如何查看linux动态链接库文件的版本等其他信息
- Java源码分析之HashMap(JDK1.8)
- 1008 数组元素循环右移问题 (20分)
- ISE应用入门的一些问题
- CAP BASE 最终一致性
- ansible+ssh自动化运维
- 给笔记本更换SSD硬盘
- 关于iOS 热更新(热修复)你必须知道的一种方法- JSPatch
- centos7下使用rpm包安装clickhouse
- 集合代码----小练习3
- Perl 语言入门学习
- python 条形图显示数值_如何在条形图的条形图中显示数值?
- Beyond Part Models: Person Retrieval with Refined Part Pooling (and A Strong Convolutional Baseline)
- 如何区分光猫、路由器和交换机?
- idea设置java-google-style
- 一文看懂未来加密行业如何应对监管?