C# 列表的行为<;T>;。从.NET 4.0更改为.NET 4.5中的排序?
我在针对.NET 4.0的项目中进行了以下测试:C# 列表的行为<;T>;。从.NET 4.0更改为.NET 4.5中的排序?,c#,.net,.net-4.0,.net-4.5,C#,.net,.net 4.0,.net 4.5,我在针对.NET 4.0的项目中进行了以下测试: [TestFixture] public class Donkey { [Test] public void TestListSorting() { var expected = new[] { MockRepository.GenerateStub<IComparable>(),
[TestFixture]
public class Donkey
{
[Test]
public void TestListSorting()
{
var expected = new[]
{
MockRepository.GenerateStub<IComparable>(),
MockRepository.GenerateStub<IComparable>()
};
var sorted = new List<IComparable>(expected);
CollectionAssert.AreEqual(expected, sorted);
sorted.Sort();
CollectionAssert.AreEqual(expected, sorted);
}
}
[TestFixture]
公驴
{
[测试]
公共void TestListSorting()
{
预期风险值=新[]
{
MockRepository.GenerateSub(),
MockRepository.GenerateStub()
};
var排序=新列表(预期);
CollectionAssert.AreEqual(预期、排序);
sorted.Sort();
CollectionAssert.AreEqual(预期、排序);
}
}
如果我在只安装了.NET4.0的机器上运行它,它就会失败。
如果我在只安装了.NET4.5的机器上运行它,它就会通过
我假设在.NET 4.5中,Sort
的实现已被更改,以便在对对象列表进行排序时保持顺序,每个对象都从CompareTo
返回0
现在,把这项测试的明显疯狂放在一边。我知道依靠这种行为是疯狂的。
这肯定是一个突破性的变化?关于.NET 4.0和4.5之间的兼容性,未在上列出
这有什么原因吗?我错过什么了吗?是否有其他页面显示实际的突破性变化?我应该坐下来停止恐慌吗?对于列表。Sort
表示使用的排序不稳定,因此可能无法保持相等元素的顺序;它没有指定相等元素的特定重新排序,因此您不能真正将此更改称为中断更改 来自
此实现执行不稳定排序;也就是说,如果两个元素相等,它们的顺序可能不会被保留
看起来订单不可靠,因此测试无效。另外,您为什么还要测试
排序
方法呢?对我来说似乎是一个不必要的测试。正如@Rawling所说,看看:
此实现执行不稳定排序;也就是说,如果两个元素相等,它们的顺序可能不会被保留
所以,您正在尝试测试一些显式记录为未定义的内容。这不是一个突破性的变化。我看不到任何变化。正如其他人已经写的,两个版本都执行不稳定的排序。这意味着您不能依赖于元素的顺序来进行相等的比较。在分拣过程中,它们的顺序可能会改变,也可能不会改变。这当然不是一个突破性的变化 请参阅:我以前已经回答了一个问题。排序方法已在4.5和4.0之间更改,从快速排序更改为快速排序 它实际上更快,但仍然不是一个稳定的sort1,也就是说,通过保持相等项的顺序,每次执行都有相同的输出。由于没有实现
List.Sort
是一种稳定的排序,我认为您运行单元测试的次数不足以使它在两个运行时都出错
我试图用等价的代码和返回0的比较器自己复制它。在.NET 4.5和.NET 3.5中,有时保留列表顺序,有时不保留
即使它确实将排序类型从稳定更改为不稳定,这也不是一个突破性的更改。所使用的排序类型和确切的输出不属于List.sort
合同的一部分。合同保证的所有方法是,您的项目将根据所使用的比较器按顺序排序
不过,这很有趣,因为[MSDN文档](http://msdn.microsoft.com/en-us/library/b0zbh7b6.aspx)仍然说它使用快速排序(通过“Array.Sort”),但如果您要单步遍历.NET引用源,则情况并非如此。
1根据混合使用
快速排序
和堆排序
的定义,它应该是一种不稳定的排序。即使是算法设计者David Musser也指出:
Introsort和quicksort一样,是不稳定的——不保留等价元素的顺序——因此仍然需要对稳定的排序例程有单独的要求
像这样的问题通常会出现新的框架版本。有一些是3.5版的→ 4.0过渡和升级 对于这个版本的特殊更改,如您的问题所示,已经出现了两个元素的数组或
列表的差异。另一个简单的例子是:
using System;
using System.Linq;
namespace SortTest
{
static class Program
{
static void Main()
{
var arr = new[] { new { Name = "Mary", Age = 17, }, new { Name = "Louise", Age = 17, }, };
Array.Sort(arr, (x, y) => x.Age.CompareTo(y.Age));
Console.WriteLine(string.Join(",", arr.Select(x => x.Name)));
}
}
}
在.NET4.0中,这将打印出路易丝、玛丽
。元素被交换。然而,在.NET4.5中,它打印的是玛丽、路易丝。请注意,这两个女孩年龄相同
List.Sort
实例方法和Array.Sort
静态方法被记录为非稳定排序。他们可以自由地按照他们想要的任何顺序留下相同“大小”的元素。因此,您的代码不能对等价元素的顺序做出任何假设
相反,Linq的OrderBy
方法执行稳定的排序。所以
var ordered = arr.OrderBy(x => x.Age);
被要求不要交换玛丽和路易丝,因为他们有相同的年龄
仍然说它使用快速排序,可能无法保持秩序。尽管如此。(还提到它被改为“内省排序”,这是一种不稳定的算法,但却是一种不同的算法。)可能发生的情况是,QuickSort的修改方式使这个微不足道的排序看起来稳定。(pivot的选择可能不同。)我不确定如何构造一个测试用例来最终证明当前使用的排序算法是否稳定,但比较两个元素不是这样的;排序((x,y)=>0)代码>+1:谢谢你在另一个答案中的精彩解释。我的速度很慢,所以在阅读之前我不理解下面的其他答案。MSDN文档已经更新,以反映自编写此答案以来的这一变化。