在浏览 Enumerable 类的 .Net Framework 源代码时,我发现它的内部 EnumerableSorter 类 CompareKeys method用于排序的有以下一行:
return descending ? -c : c;
其中 c
是 IComparer.Compare Method (T, T) 的结果方法调用,这实际上并不强制我们仅使用 -1、1 或 0 来表示排序。
考虑到 -Int32.MinValue == Int32.MinValue
由于整数溢出,它可能导致不正确的排序,如以下代码片段所示:
public class Value : IComparable<Value>
{
private readonly Int32 _value;
public Value(Int32 value)
{
this._value = value;
}
public Int32 CompareTo(Value other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
var cmp = this._value.CompareTo(other._value);
if (cmp > 0)
return Int32.MaxValue;
if (cmp < 0)
return Int32.MinValue;
return 0;
}
public override String ToString()
{
return this._value.ToString();
}
}
private static void Print<T>(String header, IEnumerable<T> values)
{
Console.WriteLine(header);
foreach (var item in values)
{
Console.WriteLine(item);
}
Console.WriteLine();
}
public static void Main()
{
try
{
var notSorted = new[] { 1, 3, 2 }
.Select(i =>
new Value(i))
.ToArray();
Print("Not sorted", notSorted);
Print("Sorted by", notSorted.OrderBy(item => item));
Print("Sorted by descending", notSorted.OrderByDescending(item => item));
}
catch (Exception exc)
{
Console.WriteLine(exc);
}
Console.WriteLine("Press any key...");
Console.ReadKey(true);
}
对于 OrderByDescending
它产生:
Sorted by descending 3 1 2
这是预料之中的,但也是一个明显不正确的结果。
所以这似乎是 .Net 中的一个缺陷,但如果 CompareTo
以合理的方式实现则不太可能发生。我说得对吗?
更新:
正如 SLaks 所指出的这个问题早已为人所知,但尽管发布了所有新版本,但仍未得到解决 - https://connect.microsoft.com/VisualStudio/feedback/details/634949/orderbydescending-fails-in-linq-to-objects-when-a-comparer-returns-int-minvalue
正如 usr 所指出的.Net Core 已修复此问题 - https://github.com/dotnet/corefx/blob/35e03c78d89d02f2d3b4a1f8b277a35c88f45750/src/System.Linq/src/System/Linq/OrderedEnumerable.cs#L628
最佳答案
似乎没有多少答案可以做出,所以:
正如 SLaks 所指出的,该问题早已为人所知,但从未在 .NET Framework 中得到修复,尽管有所有新版本(截至目前为 .Net 4.6.1)- https://connect.microsoft.com/VisualStudio/feedback/details/634949/orderbydescending-fails-in-linq-to-objects-when-a-comparer-returns-int-minvalue .
避免此问题的唯一方法是不从 CompareTo
实现中返回 Int32.MinValue
。
但正如 usr 所指出的那样 .Net Core 已修复此问题 - https://github.com/dotnet/corefx/blob/35e03c78d89d02f2d3b4a1f8b277a35c88f45750/src/System.Linq/src/System/Linq/OrderedEnumerable.cs#L628
关于c# - 由于整数溢出,OrderByDescending 操作不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35537357/