非泛型容器的缺点:

  (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#泛型类容器的更多相关文章

  1. java面向对象---对象容器

    泛型类--ArrayList<>; 2.对象数组中的每个元素都是对象的管理者而并非对象本身!!!!! 3.java类的基本数据类型 基本数据类型 包装类 byte Byte short S ...

  2. 跟我一起学STL(2)——vector容器详解

    一.引言 在上一个专题中,我们介绍了STL中的六大组件,其中容器组件是大多数人经常使用的,因为STL容器是把运用最广的数据结构实现出来,所以我们写应用程序时运用的比较多.然而容器又可以序列式容器和关联 ...

  3. 依赖注入容器Autofac的详解

    Autofac和其他容器的不同之处是它和C#语言的结合非常紧密,在使用过程中对你的应用的侵入性几乎为零,更容易与第三方的组件集成,并且开源,Autofac的主要特性如下: 1,灵活的组件实例化:Aut ...

  4. java中的容器问题

    小小的总结一下java中的容器问题. 一.三个知识点 1.迭代器 1).java.util.Interator + hasnext(); next(); remove(); 2).java.lang. ...

  5. C#中泛型容器Stack<T>

    我以前都是学出c,c++,这个学期开始学c#有点不适应,在编程中遇到些问题,所以自己在网上查了些资料,翻了一下书,写一些总结. 关于c#中Stack<T>泛型容器: <1>st ...

  6. 2015第22周六Java反射、泛型、容器简介

    Java的反射非常强大,传递class, 可以动态的生成该类.取得这个类的所有信息,包括里面的属性.方法以及构造函数等,甚至可以取得其父类或父接口里面的内容. obj.getClass().getDe ...

  7. C#核心语法讲解-泛型(详细讲解泛型方法、泛型类、泛型接口、泛型约束,了解协变逆变)

    泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性.泛型为.NET框架引入了类型参数(type parameters)的概念.类型参数使得设计类和方法时,不必确定一个或多个具 ...

  8. Java并发(一)——线程安全的容器(上)

    Java中线程安全的容器主要包括两类: Vector.Hashtable,以及封装器类Collections.synchronizedList和Collections.synchronizedMap: ...

  9. JAVA之旅(二十一)——泛型的概述以及使用,泛型类,泛型方法,静态泛型方法,泛型接口,泛型限定,通配符

    JAVA之旅(二十一)--泛型的概述以及使用,泛型类,泛型方法,静态泛型方法,泛型接口,泛型限定,通配符 不知不觉JAVA之旅已经写到21篇了,不得不感叹当初自己坚持要重学一遍JAVA的信念,中途也算 ...

随机推荐

  1. Linux phpbb论坛的安装(中文版)

    1:建立文件夹

  2. JAVA基础知识之NIO.2——Path,Paths,Files

    NIO.2 JDK7对NIO进行了重大改进,主要包含以下两方面 新增Path接口,Paths工具类,Files工具类. 这些接口和工具类对NIO中的功能进行了高度封装,大大简化了文件系统的IO编程. ...

  3. 深入对比数据科学工具箱:Python和R之争

    建议:如果只是处理(小)数据的,用R.结果更可靠,速度可以接受,上手方便,多有现成的命令.程序可以用.要自己搞个算法.处理大数据.计算量大的,用python.开发效率高,一切尽在掌握. 概述 在真实的 ...

  4. Oracle指定运行变量

    1定义:运行时变量可以让我们和sql语句之间有个交互,允许我们执行sql语句时动态传递参数 2.语法: &varName 3.运行时变量可以出现在任意位置 例如: select &co ...

  5. 阻抗计算公式、polar si9000(教程)

    给初学者的一直有很多人问我阻抗怎么计算的. 人家问多了,我想给大家整理个材料,于己于人都是个方便.如果大家还有什么问题或者文档有什么错误,欢迎讨论与指教!在计算阻抗之前,我想很有必要理解这儿阻抗的意义 ...

  6. VirtualProvider (VirtualCube)虚拟立方体

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  7. mysql5.x(<7) sql文件导入到5.7

    一.修改sql—model http://www.linuxidc.com/Linux/2016-09/135372.htm

  8. hdu4734 F(x)

    链接 这题当时在网络赛时很费劲的推出来的,以递推的形式写出来的,一些边界点特别不好控制,靠看数据改出来的.现在改出dfs形式,也是很简单的. 因为f(x)的数不会很大,直接保留前面枚举的数得出的结果即 ...

  9. Html_Img元素 设置图片与其他元素横排高度一致

    <img id="numAdd" src="~/Images/jia.jpg" style="width:30px;height:30px;ve ...

  10. 【转】关于 Web GIS

    以下部分选自2015-03-01出版的<Web GIS从基础到开发实践(基于ArcGIS API for JavaScript)>一书中的前言部分: Web GIS 概念于1994 年首次 ...