非泛型容器的缺点:

  (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. hibernate检索方式(HQL 检索方式,QBC 检索方式,本地 SQL 检索方式)

    hibernate有五种检索方式,这儿用 单向的一对多的映射关系 例子,这儿有后三种的方式: 导航对象图检索方式: 根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的 OID 来检索对象 ...

  2. sql注入过滤的公共方法

    /// <summary> ///SQL注入过滤 /// </summary> /// <param name="InText">要过滤的字符串 ...

  3. crontab 的使用

    1. 创建一个文件  mycrontab 2. 将此文件运用到系统的定时器中     crontab  mycrontab 3. crontab -e     (或直接编辑  mycrontab, 但 ...

  4. sqlite创建表

    create table bike (id ) primary key, password ));

  5. DSO、CUBE区别(覆盖、合计)

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

  6. 安装了ubuntu14.04+windows7双系统的笔记本启动后出现grub rescue>提示符

    解决思想如下: 1.在grub rescue>提示符处输入ls  即可看到该命令列出了硬盘上的所有分区,找到安装了linux的分区,我的安装在(hd0,msdos8)下,所以我以(hd0,msd ...

  7. createjs 的 bitmapdata类

    今天测试一个功能,在效率上出现了问题.2D舞台绘制了大量的元素,联想到AS3的 bitmapdata.darw() 功能,遗憾是createjs官方类 中没有bitmapdata类. 好在已经有大神替 ...

  8. c#入门笔记(1)数据类型

    1.c#有三种数据类型,分别是数值型,引用类型,指针类型. 2.数值类型 2.1整数类型:sbyte,byte,short,ushort ,int uint,long,ulong(u开头是无符号,范围 ...

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

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

  10. NPM 使用介绍

    NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种: 允许用户从NPM服务器下载别人编写的第三方包到本地使用. 允许用户从NPM服务器下载并 ...