IEqualityComparer和IEquatable在Enumerable.SequenceEqual方法中的作用是什么

Mis*_*hax 1 .net linq equality

MSDN上的这个页面上,他们描述SequenceEqualEnumerable该类的方法.

在页面中间,它指出:

如果要比较序列中对象的实际数据而不是仅仅比较它们的引用,则必须在类中实现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;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我的类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));
Run Code Online (Sandbox Code Playgroud)

..我得到的True并不False像我期望的那样阅读文档.这实际上是如何工作的?

Los*_*ter 5

IEquatable由像Dictionary这样的泛型集合使用来确定两个对象是否相等.如果对象未实现IEquatable,则使用Object.Equals方法.

为什么要实现IEquatable?它具有比Object.Equals更好的性能,因为该对象不需要进行转换.

何时不实现IEquatable? 一些开发人员认为你应该只在密封的类上实现它.

如果在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;
...
Run Code Online (Sandbox Code Playgroud)

EqualityComparer.Default检查类型T是否实现System.IEquatable接口,如果是,则返回使用该实现的EqualityComparer.否则,它返回一个EqualityComparer,它使用由T提供的Object.EqualsObject.GetHashCode的覆盖.这就是调用Object.Equals的原因.