Jep*_*sen 8 c# linq sorting algorithm base-class-library
考虑LINQ下面简单的代码OrderBy和ThenBy:
static void Main()
{
var arr1 = new[] { "Alpha", "Bravo", "Charlie", };
var coStr = Comparer<string>.Create((x, y) =>
{
Console.WriteLine($"Strings: {x} versus {y}");
return string.CompareOrdinal(x, y);
});
arr1.OrderBy(x => x, coStr).ToList();
Console.WriteLine("--");
var arr2 = new[]
{
new { P = "Alpha", Q = 7, },
new { P = "Bravo", Q = 9, },
new { P = "Charlie", Q = 13, },
};
var coInt = Comparer<int>.Create((x, y) =>
{
Console.WriteLine($"Ints: {x} versus {y}");
return x.CompareTo(y);
});
arr2.OrderBy(x => x.P, coStr).ThenBy(x => x.Q, coInt).ToList();
}
Run Code Online (Sandbox Code Playgroud)
这只是使用一些比较器向控制台写出他们比较的内容.
在我的框架(.NET 4.6.2)的硬件和版本上,这是输出:
Strings: Bravo versus Alpha Strings: Bravo versus Bravo Strings: Bravo versus Charlie Strings: Bravo versus Bravo -- Strings: Bravo versus Alpha Strings: Bravo versus Bravo Ints: 9 versus 9 Strings: Bravo versus Charlie Strings: Bravo versus Bravo Ints: 9 versus 9
我的问题是:他们为什么要将查询中的项目与自身进行比较?
在第一种情况下,在--分隔符之前,它们进行四次比较.其中两个比较了一个条目("Strings:Bravo vs. Bravo").为什么?
在第二种情况下,不应该需要求助于比较Q属性(整数); 因为值中没有重复(wrt.序数比较)P,所以不需要打破平局ThenBy.我们仍然看到"Ints:9对9"两次.为什么使用ThenBy具有相同参数的比较器?
注意:任何比较器必须0在比较某些东西时返回.因此,除非算法只是想检查我们是否正确实现了比较器(无论如何它都无法完全执行),发生了什么?
请注意:我的示例中的查询所产生的元素中没有重复项.
我在另一个例子中看到了同样的问题,从查询中产生了更多的条目.上面我举一个小例子.出现这种情况有一个甚至数产生的元素,也是如此.
InB*_*een -1
好吧,让我们看看这里的可能性:
T是一个值类型
为了检查它是否正在将一个项目与自身进行比较,它首先需要检查两个项目是否相同。你会怎么做?
您可以先打电话,如果商品不一样,Equals再打电话。CompareTo你真的想这么做吗?成本与Equals比较的成本大致相同,因此您实际上会将订购成本加倍,到底是为了什么?OrderBy只是比较所有项目,期间。
T是一个引用类型
c# 不允许您仅使用通用约束进行重载,因此您需要在运行时检查是否T是引用类型,然后调用将更改上述行为的特定实现。您想在每种情况下都承担该费用吗?当然不是。
如果比较成本很高,则在比较逻辑中实现参考优化,以避免在将项目与其自身进行比较时产生愚蠢的成本,但该选择必须是您的。我很确定string.CompareTo正是这样做的。
我希望这能让我的答案更清楚,对之前的简短回答感到抱歉,我的推理并不那么明显。