出于好奇:使用以下扩展方法对一堆对象进行排序时使用了什么比较器?
OrderBy(x=> x)
背景:我必须检查两个ISet< T>实例包含相同的元素,并考虑使用
bool setsEqual = MySet.SequenceEqual(OtherSet);
方法。由于集合中包含的那些元素的顺序未定义且可能不同,因此在内部顺序不相同的情况下,SequenceEqual将失败。所以我必须明确定义一个订单。由于订单算法本身完全不相关,只要它稳定,我只使用“身份”lambda表达式:
bool setsEqual = MySet.OrderBy(x => x).SequenceEqual(OtherSet.OrderBy(x => x);
但是“比较对象本身”对代码意味着什么呢?由于这个OrderBy扩展方法是通用的,所以必须有一个默认的比较算法,它能够在不知道更多关于它的情况下对对象进行排序,这意味着必须将排序的比较委托给集合的类型。元素本身。是否存在元素类型必须支持的接口,或者是否存在默认比较器(可能是比较对象的内部存储器地址)?
答案 0 :(得分:1)
要回答排序问题:排序使用IComparable<T>
或IComperable
(如果未实施)。 IComperable
接口强制您实施int CompareTo(object)
方法(或int CompareTo(T)
方法,如果您使用的是打字版本)。
元素的顺序由int的符号决定。返回的值解释如下:
0
:这两个对象是等价的(即相同的)-1
:比较对象在此对象之前(即在此对象之前)1
:比较对象跟随此对象(即在此对象之后)忽略实际值,标志是最重要的。如果您实现自己的IComparable
接口,则必须选择排序顺序的语义。
许多对象已经实现了IComparable
,就像你的所有数字,字符串等一样。如果你需要对你自己创建的对象进行排序,你需要明确地实现它。如果您打算将这些对象显示在屏幕上的列表中,这并不是一种不好的做法。
至于您的具体情况,您只需确定一个集合和另一个IEnumerable
是否相同,那么您将使用在ISet<T>.SetEquals(IEnumerable<T>)
中实现的方法标准库集实现。根据定义,集合仅保证值是唯一的,因此只要元素的数量相同,您只需要检测一个IEnumerable
中的所有元素都可以在集合中找到。
答案 1 :(得分:0)
该方法使用IComparable<T>
- 或IComparable
- 接口,具体取决于两者中的哪一个。如果没有实现,则顺序是任意的。
但是,在比较集合之前,您不需要为实例订购。只需循环一组并检查其所有元素是否都包含在另一组中。或者使用它:
var areEqual = firstSet.All(x => secondSet.Contains(x)) && secondSet.All(x => firstSet.Contains(x));
甚至更简单:
var areEqual = !firstSet.Except(secondSet).Any() && !secondSet.Except(firstSet).Any();
两种方式的执行速度比您的appraoch快得多,因为当找到第一个不适合的元素时,元素的迭代会停止。使用OrderBy
将循环所有元素,无论是否已存在不匹配。
答案 2 :(得分:0)
与平等不同,没有&#39;默认&#39;比较一般的对象。
对于任何类型Comparer<TKey>.Default
,TKey
似乎总是返回比较器。如果无法确定合理的比较方法,则会出现异常,但只有在使用比较器时才会出现异常。
至少有一个对象必须实现IComparable。