C#泛型类容器
非泛型容器的缺点:
(1) 性能问题。
在使用值类型时,必须将值类型装箱(Boxing)以便推送和存储,并且在将值类型从容器中取出时将其取消装箱(Unboxing)。装箱和取消装箱都会根据值类型的权限造成重大的性能损失。而且,装箱和取消装箱操作还会增加托管堆上的压力,导致更多的垃圾收集工作,这对于性能而言也不好。即使是在使用引用类型而不是值类型时,仍然存在性能损失,因为必须强制地将 object转换为需要的实际类型进行类型,造成强制类型转换开销,代码如下:
Container c = new Container();
c.Insert("1");
string number = (string)c.Delete();
(2) 类型安全。
类型转换难以保证每次转换都是成功的,这将导致某些错误在编译时无法被检查出来,而在运行时发生异常。因为编译器允许在任何类型和object 之间进行强制类型转换,所以将丢失编译时类型安全。
(3) 工作效率。
编写类型特定的数据结构是一项乏味、重复且易于出错的工作。并且,无法预知未知类型的使用情况,因此还必须保持基于 object 的数据结构。
泛型容器的完整 C#实现
public class Container<T>
{
readonly int m_Size;
private int m_ContainerPointer;
T[] m_Items;
public Container()
: )
{
m_ContainerPointer = -;
m_Items = ];
}
public Container(int size)
{
m_Size = size;
m_ContainerPointer = -;
m_Items = new T[size];
}
public int Count
{
get { return m_ContainerPointer; }
}
public bool IsEmpty
{
; }
}
public bool IsFull
{
; }
}
public void Insert(object item)//在容器的尾部插入一个元素
{
if (IsFull)
{
Console.WriteLine("Container is full!");
return;
}
m_Items[++m_ContainerPointer] = (T)item;
}
public object Delete()//从容器的尾部删除一个元素
{
)
{
return m_Items[m_ContainerPointer--];
}
return null;
}
}
表面上,C# 泛型的语法看起来与 C++模板类似,但是编译器实现和支持它们的方式存在重要差异。与 C++模板相比,C#泛型可以提供增强的安全性,但是在功能方面也受到某种程度的限制。 在一些 C++编译器中, 在通过特定类型使用模板类之前,编译器甚至不会编译模板代码。当确实指定了类型时,编译器会以内联方式插入代码,并且将每个出现一般类型参数的地方替换为指定的类型。此外,每当使用特定类型时,编译器都会插入特定于该类型的代码,而不管是否已经在应用程序中的其他某个位置为模板类指定了该类型。C++链接器负责解决该问题,并且并不总是有效。这可能会导致代码膨胀,从而增加加载时间和内存足迹。在.NET Framework 2.0 中,泛型在 IL(中间语言)和 CLR 本身中具有本机支持。在编译泛型 C#代码时,首先编译器会将其编译为 IL,就像其他任何类型一样。但是,IL 只包含实际特定类型的参数或占位符,并有专用的 IL 指令支持
泛型操作。泛型代码的元数据中包含泛型信息。真正的泛型实例化工作以“on-demand”的方式,发生在 JIT 编译时。当进行 JIT 编译时,JIT 编译器用指定的类型实参来替换泛型 IL 代码元数据中的 T,进行泛型类型的实例化。这会向 JIT 编译器提供类型特定的 IL 元数据定义,就好像从未涉及到泛型一样。这样,JIT 编译器就可以确保方法参数的正确性,实施类型安全检查,甚至执行类型特定的 IntelliSense。当.NET 将泛型 IL 代码编译为本机代码时, 所产生的本机代码取决于指定的类型。如果本机指定的是值类型,则 JIT 编译器将泛型类型参数替换为特定的值类型, 并且将其编译为本机代码。 JIT 编译器跟踪已经生成的类型特定的 IL 代码。如果 JIT 编译器用已经编译为本机代码的值类型编译泛型 IL 代码,则只是返回对该 IL 代码的引用。因为 JIT 编译器在以后的所有场合中都将使用相同的值类型特定的 IL 代码,所以不存在代码膨胀问题。如果本机指定的是引用类型,则 JIT 编译器将泛型 IL 代码中的泛型参数替换为 object,并将其编译为本机代码。在以后的任何针对引用类型而不是泛型类型参数的请求中,都将使用该代码。JIT 编译器只会重新使用实际代码。实例仍然按照它们离开托管堆的大小分配空间,并且没有强制类型转换。
泛型的好处
泛型使代码可以重用,类型和内部数据可以在不导致代码膨胀的情况下更改,而不管是值类型还是引用类型。可以一次性地开发、测试和部署代码,通过任何类型(包括将来的类型)来重用它,并且全部具有编译器支持和类型安全。因为泛型代码不会强行对值类型进行装箱和取消装箱, 或者对引用类型进行向下强制类型转换,所以性能得到显著提高。对于值类型,性能通常会提高 200%;对于引用类型,在访问该类型时,可以预期性能最多提高 100%(当然,整个应用程序的性能可能会提高,也可能不会提高) 。
C#泛型类容器的更多相关文章
- java面向对象---对象容器
泛型类--ArrayList<>; 2.对象数组中的每个元素都是对象的管理者而并非对象本身!!!!! 3.java类的基本数据类型 基本数据类型 包装类 byte Byte short S ...
- 跟我一起学STL(2)——vector容器详解
一.引言 在上一个专题中,我们介绍了STL中的六大组件,其中容器组件是大多数人经常使用的,因为STL容器是把运用最广的数据结构实现出来,所以我们写应用程序时运用的比较多.然而容器又可以序列式容器和关联 ...
- 依赖注入容器Autofac的详解
Autofac和其他容器的不同之处是它和C#语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成,并且开源,Autofac的主要特性如下: 1,灵活的组件实例化:Aut ...
- java中的容器问题
小小的总结一下java中的容器问题. 一.三个知识点 1.迭代器 1).java.util.Interator + hasnext(); next(); remove(); 2).java.lang. ...
- C#中泛型容器Stack<T>
我以前都是学出c,c++,这个学期开始学c#有点不适应,在编程中遇到些问题,所以自己在网上查了些资料,翻了一下书,写一些总结. 关于c#中Stack<T>泛型容器: <1>st ...
- 2015第22周六Java反射、泛型、容器简介
Java的反射非常强大,传递class, 可以动态的生成该类.取得这个类的所有信息,包括里面的属性.方法以及构造函数等,甚至可以取得其父类或父接口里面的内容. obj.getClass().getDe ...
- C#核心语法讲解-泛型(详细讲解泛型方法、泛型类、泛型接口、泛型约束,了解协变逆变)
泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性.泛型为.NET框架引入了类型参数(type parameters)的概念.类型参数使得设计类和方法时,不必确定一个或多个具 ...
- Java并发(一)——线程安全的容器(上)
Java中线程安全的容器主要包括两类: Vector.Hashtable,以及封装器类Collections.synchronizedList和Collections.synchronizedMap: ...
- JAVA之旅(二十一)——泛型的概述以及使用,泛型类,泛型方法,静态泛型方法,泛型接口,泛型限定,通配符
JAVA之旅(二十一)--泛型的概述以及使用,泛型类,泛型方法,静态泛型方法,泛型接口,泛型限定,通配符 不知不觉JAVA之旅已经写到21篇了,不得不感叹当初自己坚持要重学一遍JAVA的信念,中途也算 ...
随机推荐
- Swashbuckle for asp.net core 配置说明
0x00 安装 Swashbuckle 6.0 打开程序包管理器控制台,输入: Install-Package Swashbuckle -Pre 0x01 配置 Startup.cs public v ...
- OS X 下iso刻录U盘
1. 查看盘 $diskutil list /dev/disk0 #: TYPE NAME SIZE IDENTIFIER : GUID_partition_scheme *320.1 GB disk ...
- C#预处理器指令
在C#中有许多名为“预处理指令”的命令,这些命令从来不会转化为可执行代码中的命令,但会影响编译过程的各个方面.例如,使用预处理器指令可以禁止编译器编译代码的某一部分.如果计划发布两个版本的代码,即基本 ...
- OpenCV安装配置的简单记录
在ubuntu16.04下安装OpenCV 2.4.11的简单记录 1. 安装cmake,执行$apt-get install cmake即可,cmake -version验证 2. 下载OpenCV ...
- [问题2014A01] 复旦高等代数 I(14级)每周一题(第三教学周)
[问题2014A01] 试求下列 \(n\) 阶行列式的值: \[ |A|=\begin{vmatrix} 1 & x_1(x_1-a) & x_1^2(x_1-a) & \ ...
- [问题2014A02] 解答二(求和法+拆分法,由张诚纯同学提供)
[问题2014A02] 解答二(求和法+拆分法,由张诚纯同学提供) 将行列式 \(|A|\) 的第二列,\(\cdots\),第 \(n\) 列全部加到第一列,可得 \[ |A|=\begin{vma ...
- excel如何用公式判断单元格的值是否为数字、英文、中文,以及相应的计数
一.excel如何用公式判断单元格的值是否为数字.英文.中文. A列为数据列,B列为判断列=LOOKUP(CODE(ASC(A1)),{48,65,123;"数字","英 ...
- Sublime Text的使用代码块安装的模块
在众多的开发工具IDE当中.作者现在唯独深爱sublime text(以下简称st).以前做后台开发使用visual studio(以下简称vs),以及实行前后端分工也是配合后台使用vs.这里要讲述两 ...
- z-index 应用简单总结
做过页面布局的同学对z-index属性应该是很熟悉了,z-index是针对网页显示中的一个特殊属性.因为显示器是显示的图案是一个二维平面,拥有x轴和y轴来表示位置属性.为了表示三维立体的概念如显示元素 ...
- viewport和media query
viewport: 你可以定义viewport的宽度.如果你不使用width=device-width,在移动端上你的页面延伸会超过视窗布局的宽度(width=980px),如果你使用了width=d ...