为什么List.Sort()是一个实例方法,但Array.Sort()是静态的?

我试图理解这部分语言背后的devise决定。 我承认我对这一切都很陌生,但是这是最初抓到我的东西,我想知道如果我错过了一个明显的原因。 考虑下面的代码:

List<int> MyList = new List<int>() { 5, 4, 3, 2, 1 }; int[] MyArray = {5,4,3,2,1}; //Sort the list MyList.Sort(); //This was an instance method //Sort the Array Array.Sort(MyArray); //This was a static method 

为什么它们不是以同样的方式实现的 – 直观地看,如果它们都是实例方法,那么它们会更有意义。

这个问题很有趣,因为它揭示了.NETtypes系统的细节。 像值types,string和委托types,数组types在.NET中得到特殊的处理。 最值得注意的奇怪行为是,你从不显式声明一个数组types。 编译器会为您提供充足的抖动帮助。 System.Array是一个抽象types,您将在编写代码的过程中获得专用的数组types。 无论是通过显式创build一个types[]或使用在其基本实现中有一个数组的generics类。

在一个庞大的程序中,有数百个数组types并不罕见。 没关系,但是每种types都有开销。 它只是types的存储,而不是它的对象。 其中最大的一块是所谓的“方法表”。 简而言之,它是指向这个types的每个实例方法的指针列表。 类加载器和抖动器一起工作来填充这个表格。 这通常被称为“v表”,但不完全匹配,该表包含指向非虚拟和虚拟方法的指针。

你可以看到这可能导致什么,devise师担心有很多types很大的方法表。 所以想办法减less开销。

Array.Sort()是一个明显的目标。

同样的问题是不相关的genericstypes。 generics是一个很好的方法,许多方法表中的一个可以处理引用types的任何types参数的方法指针。

您正在比较两种不同types的“对象容器”:

MyList是Listtypes的generics集合,它是一个types为int的包装类,其中List<T>表示一个强types的对象列表。 List类本身提供了search,sorting和操作其包含的对象的方法。

MyArray是Arraytypes的基本数据结构。 该数组不提供与List相同的丰富的方法。 数组同时可以是单维的,多维的或锯齿状的,而开箱即用的只是单维的。

看看这个问题,它提供了关于这些数据types的更丰富的讨论: Array versus List<T>: When to use which?

如果不询问参与原始平台devise的人,很难知道。 但是,这是我的猜测。

在像C这样的老式语言中,数组是愚蠢的数据结构 – 它们没有自己的代码。 相反,他们被外部方法操纵。 当你进入一个面向对象的框架,最接近的equivilent是一个愚蠢的对象(用最less的方法)由静态方法操纵。

所以,我的猜测是,.NET数组的实现更多的是在开发初期的C风格思维的一个症状。

这可能与inheritance有关。 Array类不能从中手动派生。 但奇怪的是,你甚至可以声明一个任意数组的数组,并获得强types的System.Array的一个实例,甚至在generics允许你强types化集合之前。 数组似乎是框架的魔法部分之一。

另请注意,数组上提供的实例方法都没有大量修改数组。 SetValue()似乎是唯一一个改变任何东西。 Array类本身提供了许多可以改变数组内容的静态方法,如Reverse()和Sort()。 不知道这是否意义重大 – 也许这里有人可以给出一些背景,为什么是这样的情况。

相比之下, List<T> (这在1.0框架时期并不在其周围)以及像ArrayList (当时那样)的类只是在框架中没有特殊含义的磨工类的运行。 他们提供了一个通用的.Sort()实例方法,以便当您从这些类inheritance时,您将获得该function或可以覆盖它。

然而,这种sorting方法已经不再stream行,Linq的.OrderBy()风格sorting等扩展方法已经成为下一个发展方向。 您现在可以使用相同的机制来查询和sorting数组和列表以及任何其他可枚举对象,这真的很好。

– 编辑 –

另一个更愤世嫉俗的答案可能就是 – 这就是Java的做法,所以微软在1.0版本的框架中做了同样的事情,因为当时他们忙于追赶。

一个原因可能是因为Array.Sort是在没有generics的.NET 1.0中devise的。

我不确定,但是我想也许只是为了让数组尽可能接近原始数据。