C# .NET3.5和.NET4.0之间排序的差异
在对集合进行排序时,我遇到了.NET framework的一个非常奇怪的行为。 这种行为在.NET 3.5和4.0()之间有所不同,但更重要的是(这是我在这里真正关心的问题),在同一框架上的不同机器上,这种行为是不同的 上下文 我正在开发一个依赖于第三方软件的软件(本例中是spring.net,但这并不重要),在某个时候,它正在对一个集合进行排序,该集合的所有项都是“相等的”(比较器总是返回0)。这是而不是在我的控制下,如果排序列表的行为总是一致的,我会很好地处理它。不是 如何繁殖 在.NET 3.5中创建一个简单的项目,,并运行下面的代码。 在3.5中编译时,行为似乎是一致的,集合将被“反转”(结果为3,2,1)。 现在,请将项目目标更改为.NET 4(不是4.5),然后再次运行: 在我的机器上,它不再反转集合(一、二、三),但在其他同事的机器上,它反转集合(三、二、一)!!!我们有完全相同的设置 你能告诉我,在你的机器上,在4.0以下,它是什么吗?反转还是不反转? 我正在尝试评估我的设置是否正确 概念证明C# .NET3.5和.NET4.0之间排序的差异,c#,.net,.net-4.0,.net-4.5,C#,.net,.net 4.0,.net 4.5,在对集合进行排序时,我遇到了.NET framework的一个非常奇怪的行为。 这种行为在.NET 3.5和4.0()之间有所不同,但更重要的是(这是我在这里真正关心的问题),在同一框架上的不同机器上,这种行为是不同的 上下文 我正在开发一个依赖于第三方软件的软件(本例中是spring.net,但这并不重要),在某个时候,它正在对一个集合进行排序,该集合的所有项都是“相等的”(比较器总是返回0)。这是而不是在我的控制下,如果排序列表的行为总是一致的,我会很好地处理它。不是 如何繁殖 在.NET
还有,如果你知道为什么会这样,请告诉我 ArrayList.sort()完成的排序不稳定,因此无法预测“相同”项的排序顺序 此外,由于ArrayList.Sort()可能会使用随机机制为其快速排序算法选择轴,因此相同的项目可能会在不同的PC上,甚至在同一台PC上进行不同的排序 [编辑:我找不到任何证据表明当前实现中选择了随机轴,但数组排序仍然不稳定。我猜随机性来自
TrySZSort()
中的本机代码快速排序实现,这可能会被调用。]
同样出于兴趣,Reflector在ArrayList.Sort()中显示了这段代码(如果您深入了解一下):
它似乎在为.Net 4.5选择一种完全不同的排序算法。正如他所说,排序是在第三方代码中进行的,不能更改。信息:LINQ的排序是“稳定的”-但不是一个就地的sortMSDN清楚地表明数组。sort(以及使用它的所有东西)是不稳定的。那么你想在这里实现什么呢?如果你不能控制分类,而医生说不能保证。。。很明显,你不应该依赖订单。(旁注:LINQ的OrderBy确实提供了稳定的排序。)排序算法在.NET4中更改。这是GIGO的问题,垃圾进来,垃圾出去。写一个合适的比较器。正如我说的,问题是我不能控制任何一个(排序等)。这基本上是Spring.net中的一个bug,(幸运的是)在3.5以下时没有引起任何问题,但在切换到4.0时开始让我们头疼。似乎最好的做法是修复spring.net…可能就是这样:我们机器之间的区别在于我有VS 2012,而其他用户没有(只有2010年)。显然,安装VS 2012会替换.NET 4的一些DLL,并且可能会将排序算法更改为您前面提到的内省软件。谢谢感谢您添加Reflector(ed)代码,显示内省排序与DepthLimitedQuickSort。这对我帮助很大。
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;
}
}
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);
}
}