【问题标题】:Difference in sorting between .NET 3.5 and .NET 4.0.NET 3.5 和 .NET 4.0 之间的排序差异
【发布时间】:2013-03-11 12:17:14
【问题描述】:

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

上下文

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

如何重现

创建一个简单的项目,在 .NET 3.5 中,然后运行下面的代码。 在 3.5 中编译时,行为似乎是一致的,并且集合将被“反转”(结果为 三、二、一)。 现在,请将项目目标更改为 .NET 4 (not 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;
    }
}

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

【问题讨论】:

  • 如他所说,排序是在第三方代码中完成的,无法更改。
  • 供参考:LINQ 的排序“稳定” - 但不是就地排序
  • MSDN 明确指出 Array.Sort(以及所有使用它的东西)不稳定。那么你想在这里实现什么?如果您无法控制排序,并且文档说不能保证......显然您不应该依赖订单。 (旁注:LINQ 的 OrderBy 确实提供了稳定的排序。)
  • .NET 4 中更改了排序算法。这是一个 GIGO 问题,垃圾进,垃圾出。写一个合适的比较器。
  • 正如我所说的,问题是我无法控制其中的任何一个(排序等)。这基本上是 Spring.net 中的一个错误,(幸运的是)在 3.5 下没有引起任何问题,但在切换到 4.0 时开始让我们头疼。似乎最好的做法是修复 spring.net...

标签: c# .net .net-4.0 .net-4.5


【解决方案1】:

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

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

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

同样出于兴趣,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 选择了一种完全不同的排序算法。

【讨论】:

  • 可能是这样:似乎我们机器之间的区别在于我有VS 2012,而其他用户没有(只有2010)。显然,安装 VS 2012 替换了 .NET 4 的一些 DLL,并且可能将排序算法更改为您之前提到的 Introspective Soft。谢谢!
  • 感谢您添加 Reflector(ed) 代码,显示 IntrospectiveSort 与 DepthLimitedQuickSort。这对我帮助很大。
猜你喜欢
  • 1970-01-01
  • 2014-03-11
  • 2011-09-07
  • 2011-06-28
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多