简体   繁体   English

.NET 3.5和.NET 4.0之间的排序差异

[英]Difference in sorting between .NET 3.5 and .NET 4.0

I've come across a very weird behaviour of the .NET framework(s), when sorting a collection. 在对集合进行排序时,我遇到了一个非常奇怪的.NET框架行为。 This behaviour is different between .NET 3.5 and 4.0 ( but I think I know why ), but more importantly (and that's my real concern here), the behaviour is different accross different machines on the same framework . 这种行为在.NET 3.5和4.0之间是不同的( 但我想我知道为什么 ),但更重要的是(这是我真正关心的), 在同一框架上的不同机器上的行为是不同的

Context 上下文

I'm working on a piece of software that's relying on some third party software (spring.net in this case but it doesn't matter), and at some point, it's sorting a collection that has all its item "equal" (the comparer always return 0). 我正在开发一种依赖于某些第三方软件的软件(在这种情况下是spring.net,但这并不重要),并且在某些时候,它正在整理一个集所有项目“相等”的集合(比较器总是返回0)。 This is NOT under my control and I'd be very fine with it if the behaviour of sorting that list was always consistent. 不在我的控制之下,如果排序该列表的行为始终一致,我会很好。 It's not. 不是。

How to reproduce 如何重现

Create a simple project, in .NET 3.5 , and run the code below. 在.NET 3.5中创建一个简单的项目,然后运行下面的代码。 When compiled in 3.5, the behaviour seems to be consistent, and the collection will be "reversed" (it comes out as Three, Two, One ). 当在3.5中编译时,行为似乎是一致的,并且集合将被“反转”(它出现为Three,Two,One )。 Now, please change the project target to .NET 4 ( not 4.5 ) , and run it again: On my machine, it doesn't reverse the collection anymore (One, Two, Three), but on some other colleagues machine, it does (Three, Two, One)!!! 现在,请将项目目标更改为.NET 4( 而不是4.5 ,然后再次运行:在我的机器上,它不再反转集合(一,二,三),但在其他一些同事机器上,它确实(三二一)!!! We have exactly the same setup... 我们有完全相同的设置......

Can you please tell me, on your machine, under 4.0, which it is? 你可以告诉我,在你的机器上,4.0以下,它是什么? Reversed or not reversed? 反转还是不反转?

I'm trying to assess whether my setup is correct, or not. 我正在尝试评估我的设置是否正确。

Proof of concept 概念证明

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;
    }
}

Also, if you have any idea why this is happening, please let me know! 另外,如果你知道为什么会这样,请告诉我!

The sort done by ArrayList.Sort() is not stable, therefore you cannot predict the order in which "identical" items will sort. 由ArrayList.Sort()完成的排序不稳定,因此您无法预测“相同”项将排序的顺序。

Further, because ArrayList.Sort() may use a random mechanism to select the pivot for its QuickSort algorithm, identical items may be sorted differently on different PCs or even on the same PC. 此外,因为ArrayList.Sort()可以使用随机机制来为其QuickSort算法选择枢轴,所以相同的项目可以在不同的PC上或甚至在同一PC上被不同地分类。

[EDIT: I can't find any evidence for a random pivot being chosen in current implementations, but the array sort is still unstable. [编辑:我找不到任何在当前实现中选择随机数据的证据,但数组排序仍然不稳定。 I'm guessing the randomness comes from the native code Quicksort implementation in TrySZSort() which is what probably gets called.] 我猜测随机性来自TrySZSort()的本机代码Quicksort实现,这可能被调用。

Also for interest's sake, Reflector shows this code in the ArrayList.Sort() (if you dig in a bit): 另外为了感兴趣,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);
    }
}

which seems to be selecting an entirely different sort algorithm for .Net 4.5. 这似乎是为.Net 4.5选择完全不同的排序算法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM