在MSDN上的这个页面上,他们描述了SequenceEqual
类的Enumerable
方法。
页面中间显示:
如果要比较序列中对象的实际数据 而不是只是比较他们的引用,你必须实现 IEqualityComparer类中的通用接口。下列 代码示例显示如何在自定义数据中实现此接口 输入并提供GetHashCode和Equals方法。
然后他们展示了一个示例,他们根本没有实现IEqualityComparer<T>
接口,而是实现IEquatable<T>
。我自己完成了测试,没有实现IEqualityComparer或IEquatable,只是简单地覆盖了Object的Equals,我发现它可以解决问题。以下是样本:
class AlwaysEquals
{
override public bool Equals(Object o)
{
return true;
}
public override int GetHashCode()
{
return 1;
}
}
请注意,我的类AlwaysEquals什么都不实现,没有IEquatable,没有IEqualityComparer,什么都没有。但是,当我运行此代码时:
AlwaysEquals ae1 = new AlwaysEquals();
AlwaysEquals ae2 = new AlwaysEquals();
AlwaysEquals ae3 = new AlwaysEquals();
AlwaysEquals[] Ae1 = new AlwaysEquals[] {ae3, ae2, ae3};
AlwaysEquals[] Ae2 = new AlwaysEquals[] {ae1, ae1, ae1};
Console.WriteLine(Ae1.SequenceEqual(Ae2));
..我得到True
而不是False
正如我期望阅读文档一样。这实际上是如何工作的?
答案 0 :(得分:5)
IEquatable 来确定两个对象是否相等。如果对象没有实现IEquatable,则使用Object.Equals方法。
为什么要实现IEquatable?它具有比Object.Equals更好的性能,因为该对象不需要进行转换。
何时不实施IEquatable? Some developers believe that you should only implement it on sealed classes。
如果在SequenceEquals中指定了 IEqualityComparer ,那么它就是用于检查两个对象的等价而不是Object.Equal的那个,它是IEquatable实现。在SequenceEqual中使用它的示例是http://msdn.microsoft.com/en-us/library/bb342073%28v=vs.110%29.aspx。请注意,方法签名接受IEqualityComparer。
许多集合如Dictionary也在其构造函数
中接受IEqualityComparer回答您的问题
如果没有向SequenceEquals提供IEqualityComparer,它将使用EqualityComparer.Default。
反编译代码:
public static bool SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
{
return Enumerable.SequenceEqual<TSource>(first, second, (IEqualityComparer<TSource>) null);
}
public static bool SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
if (comparer == null)
comparer = (IEqualityComparer<TSource>) EqualityComparer<TSource>.Default;
...
EqualityComparer.Default检查类型T是否实现 System.IEquatable 接口,如果是,则返回使用该实现的EqualityComparer。否则,它返回使用的的Object.Equals 的的覆盖的EqualityComparer和 Object.GetHashCode 的由T.这就是为什么你的Object.Equals被调用。提供