【C#】数组、集合、泛型集合的区别与联系

From:http://topic.csdn.net/u/20111225/11/e3f37d75-a035-47de-bf7a-1b5106e08846.html

【数组】

  C#数组是个很重要的概念,在C#类库中,它属于基本常用的类型,和int,string等是一级别的,是C#最基础、最核心的部分,它是相同类型的一组集合,当然,它也是安全的;但数组确实也比较奇怪,它到底属于什么类型?比如int[] a,A[] a1;确实找不到a或a1的类型定义,即使在CIL中也无此定义,如果用a.GetType(),你得到是System.int32[]----这不纯属扯淡嘛,这种类型找的着吗?

  但有两点需要注意:其一,数组也是一个对象,它派生于抽象类Array;其二,数组对象的实例化和C#中其它任何引用类型的实例化都不相同,引用类型是.newobj,而数组是.newarr指令。

  PS,关于第二点:

  源码:

    public class Prime
    {
        class SampleClass { }
        class Program{
            static void Main(string[] args){
                SampleClass sc = new SampleClass();
                int[] x = new int[2] { 0, 0 };
            }
        }
    }

  汇编代码:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       17 (0x11)
  .maxstack  1
  .locals init ([0] class Test.Prime/SampleClass sc,
           [1] int32[] x,
           [2] int32[] CS$0$0000)
  IL_0000:  nop
  IL_0001:  newobj    instance void Test.Prime/SampleClass::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldc.i4.2
  IL_0008:  newarr     [mscorlib]System.Int32
  IL_000d:  stloc.2
  IL_000e:  ldloc.2
  IL_000f:  stloc.1
  IL_0010:  ret
} // end of method Program::Main

这两点很重要,我们可以推测下数组对象的类型到底是什么,诸如C#编译器遇到int[],A[],B[]……时,应该映射成各个继承Array的子类,然后才是实例化,这乍一看有理,再想想就可笑了,IL只有个.newarr指令;如果我们要用C#设计一个高效可重用的数组类,我们怎么办?这几乎是不可能的。其实数组很容易理解,刚才的newarr就说明了一切,C#中的数组操作已经固化成一个特定的指令了,这样它就和其它类型不一样了,显得低级化了;实际看来,C#数组和泛型的效率至少不低于C/C++及STL,它们不是被面向对象化了,而是虚拟了面向对象,这样看来,它们的实现不是面向对象的封装,至少是C/C++级别的特定安全实现,甚至是用汇编或机器指令写的,如此看来,再索求数组和泛型是什么类型时倒显得有些荒唐了,我们姑且就认为它是面向对象化了,当然看到的都是假象,这些假象中又最重要的一点---这个所谓的假数组对象也有一个假的索引器,这样看起来和真实对象的索引器就是一个概念。

  C#数组对象的特点就是虚拟成了面向对象,有了索引器概念,是面向对象的,是安全的,又是很高效的,当然也是最不灵活的!


【集合】

  由于要灵活,集合就产生了,它是做为一个通用的算法产生的,有ArrayList,Stack….提供了常用的容器,这种通用性是用万能的object实现的;特点就是:可以装各个类型(这违背了数组单一化原则,除非迫不得已,千万不要这么做),存在类型不安全因素,性能差劲!针对此,出现了自定义的加强版的集合-----强类型集合,它解决了安全性,但是通用性差,性能低。由此可年,通吃各种类型到成了唯一的特点,除非迫不得已,不要用。


【泛型集合】

  于是,除了有灵活性和通用性特点外,安全和高效的集合便诞生了,同时,泛型的概念也推广了。在自定义泛型集合中,引出了约束占位符类型的语法规则,要了解一下!

  泛型思考,泛型是一种思想,主要体现在算法上,它最大特点就是在不牺牲效率的前提下实现算法的通用性-----真正实现代码的重用,其抽象级别要比面向对象高;泛型是面向算法(过程)编程,脱离数据,实现算法(模式)的重用性;面向对象是面向大型软件的编程,封装数据和算法,通过继承和组合实现组件(代码)的可重用性。

  泛型类、泛型接口、泛型代理、泛型方法:
  泛型类
相比类而言,更抽象,应该体现算法和数据容器的作用,除此以外,慎用泛型,它并不是万能的!
  泛型接口相比接口而言,更体现接口约定的抽象性。
  泛型代理更能体现方法类型的抽象性。
  泛型方法更能体现算法的抽象性,泛型方法能实现的算法,一定能用函数重载实现,而函数的重载不一定能用泛型方法实现,最重要的是泛型方法内不允许有占位符类型参与各种运算操作,这大大限制了泛型的功能。

  总结:泛型类型是定义时用占位符, 占位符只能出现在泛型类型定义内或泛型方法内。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章