9

在对集合进行排序时,我遇到了 .NET 框架的一个非常奇怪的行为。这种行为在 .NET 3.5 和 4.0 之间是不同的(但我想我知道为什么),但更重要的是(这是我真正关心的问题),在同一框架上的不同机器上的行为是不同的

语境

我正在开发一个依赖于某些第三方软件的软件(在这种情况下是 spring.net,但没关系),并且在某些时候,它正在对一个所有项目“相等”的集合进行排序(比较器总是返回 0)。这不在我的控制之下,如果排序该列表的行为始终一致,我会很好。它不是。

如何重现

在 .NET 3.5 中创建一个简单的项目,然后运行下面的代码。在 3.5 中编译时,行为似乎是一致的,并且集合将被“反转”(结果为Three, Two, One)。现在,请将项目目标更改为.NET 4(不是 4.5,然后再次运行:在我的机器上,它不再反转集合(一、二、三),但在其他一些同事的机器上,它确实(三二一)!!!我们有完全相同的设置...

你能告诉我,在你的机器上,在 4.0 下,它是什么?反转还是不反转?

我正在尝试评估我的设置是否正确。

概念证明

class Program
{
    static void Main()
    {
        var collection = new ArrayList
        {
            "One",
            "Two",
            "Three",
        };

        // It should in any case write One, Two, Three
        Console.Out.WriteLine("Before sort: ");
        foreach (string item in collection)
        {
            Console.Out.WriteLine("\t"+item);
        }

        collection.Sort(new OrderComparator());

        // In .NET 3.5, it will write Three, Two, One
        // In .NET 4, it will sometimes write Three, Two, One, sometimes One, Two, Three: what is it for you?
        Console.Out.WriteLine("After sort: ");
        foreach (string item in collection)
        {
            Console.Out.WriteLine("\t" + item);
        }

        Console.Out.WriteLine("--end--");
        Console.Read();
    }
}

public class OrderComparator : IComparer
{
    public virtual int Compare(object o1, object o2)
    {
        return 0;
    }
}

另外,如果您知道为什么会发生这种情况,请告诉我!

4

1 回答 1

9

ArrayList.Sort() 完成的排序并不稳定,因此您无法预测“相同”项目的排序顺序。

此外,由于 ArrayList.Sort() 可能使用随机机制来为其 QuickSort 算法选择主元,因此相同的项目可能在不同的 PC 甚至同一台 PC 上以不同的方式排序。

[编辑:我找不到任何证据表明在当前实现中选择了随机枢轴,但数组排序仍然不稳定。我猜随机性来自本机代码 Quicksort 实现,TrySZSort()其中可能会被调用。]

同样出于兴趣,Reflector 在 ArrayList.Sort() 中显示了这段代码(如果你深入研究的话):

internal void Sort(int left, int length)
{
    if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
    {
        this.IntrospectiveSort(left, length);
    }
    else
    {
        this.DepthLimitedQuickSort(left, (length + left) - 0x1, 0x20);
    }
}

这似乎为.Net 4.5选择了一种完全不同的排序算法。

于 2013-03-11T12:21:47.927 回答