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

时间:2011-07-15 22:44:11

标签: c# .net

我正在努力理解这部分语言背后的设计决策。我承认我对这一切都很陌生,但这最初引起了我的注意,我想知道我是否错过了一个明显的原因。请考虑以下代码:

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

为什么它们不是以同样的方式实现 - 直觉上对我来说如果它们都是实例方法会更有意义吗?

6 个答案:

答案 0 :(得分:30)

这个问题很有趣,因为它揭示了.NET类型系统的细节。与值类型,字符串和委托类型一样,数组类型在.NET中得到特殊处理。最值得注意的奇怪行为是您从未明确声明数组类型。编译器会为您提供充分的抖动帮助。 System.Array是一种抽象类型,在编写代码的过程中,您将获得专用的数组类型。通过显式创建类型[]或使用在其基本实现中具有数组的泛型类。

在一个大型程序中,拥有数百种阵列类型并不罕见。哪个没问题,但每种类型都有开销。它只是类型所需的存储,而不是它的对象。最大的一块是所谓的“方法表”。简而言之,它是指向该类型的每个实例方法的指针列表。类加载器和抖动一起工作以填充该表。这通常称为“v-table”,但不是很匹配,该表包含指向非虚拟和虚拟方法的指针。

你可以看到这可能导致的地方,设计师担心有很多类型的大方法表。所以寻找减少开销的方法。

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

同样的问题与泛型类型无关。泛型的一个很好的,很多,一个方法表中的一个可以处理引用类型的任何类型参数的方法指针。

答案 1 :(得分:5)

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

MyList是类型List的通用集合,类型为int的包装类,其中List<T>表示强类型的对象列表。 List类本身提供了搜索,排序和操作其包含对象的方法。

MyArrayArray类型的基本数据结构。 Array不提供与List相同的丰富方法。阵列可以同时是单维的,多维的或锯齿状的,而开箱即用的列表只是单维的。

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

答案 2 :(得分:3)

这可能与继承有关。无法手动派生Array类。但奇怪的是,你可以声明一个任何东西的数组并得到一个强类型的System.Array实例,甚至在泛型允许你有强类型集合之前。数组似乎是框架中那些神奇的部分之一。

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

相比之下,List<T>(在1.0框架日期间不存在)和像ArrayList这样的类(当时大概都是这样)只是在磨机类中运行而没有特殊的在框架内的意义。它们提供了一个通用的.Sort()实例方法,这样当你从这些类继承时,你将获得该功能或者可以覆盖它。

然而,无论如何,这些排序方法已经不再流行,因为像Linq的.OrderBy()样式排序这样的扩展方法已成为下一个发展方向。您现在可以使用相同的机制查询和排序数组和列表以及任何其他可枚举对象,这非常非常好。

- 编辑 -

另一个更愤世嫉俗的答案可能只是 - that's how Java did it所以微软在1.0版本的框架中以同样的方式做到了这一点,因为当时他们正在忙着追赶。

答案 3 :(得分:3)

没有问过参与原始平台设计的人,很难知道。但是,这是我的猜测。

在较旧的语言中,如C,数组是愚蠢的数据结构 - 它们没有自己的代码。相反,他们被外部方法操纵。当您进入面向对象的框架时,最接近的等值是一个由静态方法操纵的哑对象(使用最少的方法)。

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

答案 4 :(得分:2)

一个原因可能是因为Array.Sort是在.NET 1.0中设计的,它没有泛型。

答案 5 :(得分:0)

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