EqualityComparer <T> .Default vs. T.Equals

tak*_*krl 31 .net c# generics comparison iequalitycomparer

假设我有一个MyClass<T>需要比较两个类型对象的泛型<T>.通常我会做......

void DoSomething(T o1, T o2)
{
  if(o1.Equals(o2))
  {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

现在假设我MyClass<T>有一个支持传递自定义的构造函数IEqualityComparer<T>,类似于Dictionary<T>.在那种情况下,我需要做......

private IEqualityComparer<T> _comparer;
public MyClass() {}
public MyClass(IEqualityComparer<T> comparer)
{
  _comparer = comparer;
}
void DoSomething(T o1, T o2)
{
  if((_comparer != null && _comparer.Equals(o1, o2)) || (o1.Equals(o2)))
  {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

要删除这个冗长的if语句,_comparer如果使用常规构造函数,我可以默认使用'default comparer'.我搜索了类似的东西,typeof(T).GetDefaultComparer()却找不到类似的东西.

我找到了EqualityComparer<T>.Default,我可以用它吗?然后这个片段......

public MyClass()
{
  _comparer = EqualityComparer<T>.Default;
}
void DoSomething(T o1, T o2)
{
  if(_comparer.Equals(o1, o2))
  {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

...提供与使用o1.Equals(o2)所有可能情况相同的结果?

(作为旁注,这是否意味着我还需要使用任何特殊的通用约束<T>?)

Dan*_*rth 42

它应该是相同的,但不能保证,因为它取决于类型的实现细节T.
说明:
如果没有约束T,o1.Equals(o2)将调用Object.Equals,即使是Timplements IEquatable<T>.
EqualityComparer<T>.Default但是,只会使用Object.Equals,如果T没有实现IEquatable<T>.如果它确实实现了该接口,则使用IEquatable<T>.Equals.
只要T执行Object.Equals刚刚调用IEquatable<T>.Equals的结果是一样的.但在以下示例中,结果不一样:

public class MyObject : IEquatable<MyObject>
{
    public int ID {get;set;}
    public string Name {get;set;}

    public override bool Equals(object o)
    {
        var other = o as MyObject;
        return other == null ? false : other.ID == ID;
    }    

    public bool Equals(MyObject o)
    {
        return o.Name == Name;
    } 
}
Run Code Online (Sandbox Code Playgroud)

现在,实现这样的类没有任何意义.但是如果实施者MyObject只是忘了覆盖,你就会遇到同样的问题Object.Equals.

结论:
使用EqualityComparer<T>.Default是一种很好的方法,因为您不需要支持错误的对象!

  • 任何使用IEquatable.Equals和object.Equals执行不同操作的类型已经注定了:) (18认同)
  • @MarcGravell你无法避免它,如果你继承了一个密封了它的`object.Equals`实现的类,比如`DependencyObject`.在这些情况下,使用`EqualityComparer <T> .Default`来确保调用自己的`Equals`实现是非常重要的. (6认同)
  • 如果重写Equals,请不要忘记覆盖GetHashCode - http://stackoverflow.com/questions/23757210/c-sharp-dictionary-file-path-custom-equalitycomparer [编译器警告(级别3)CS0659)](http ://msdn.microsoft.com/en-us/library/xxhbfytk%28v=vs.90%29.aspx) (3认同)
  • 返回语句看起来更像`return other!= null && other.ID == ID;` (2认同)