2012-01-03 40 views
3

已解决! 这工作,我需要告诉牛逼实现当然IEquatable编译器...为什么这不起作用? (Generic Equals Helper)

public static bool secureEquals<T>(T obj1, object obj2) 
    where T: class, IEquatable<T> 
{... 

public static bool secureEquals<T>(T obj1, T obj2) 
    where T: class, IEquatable<T> 
{.... 

问:

我试图把IEquatable实现重复功能和equals覆盖成独立的静态类,像这样:

public static class EqualsHelper 
{ 
    public static bool secureEquals<T>(T obj1, object obj2) 
     where T : class 
    { 
     if (obj2 is T) 
     { 
      return secureEquals(obj1, obj2 as T); 
     } 
     else 
     { 
      return false; 
     } 
    } 

    public static bool secureEquals<T>(T obj1, T obj2) 
    { 
     if (obj1 == null) 
     { 
      if (obj2 != null) 
       return false; 
     } 
     else 
     { 
      if (!obj1.Equals(obj2)) //this calls Dummy.Equals(object other)! 
       return false; 
     } 

     return true; 
    } 


    public static bool secureEquals(double[] obj1, double[] obj2) 
    { 
     if (obj1.Length != obj2.Length) 
      return false; 

     for (int i = 0; i < obj1.Length; ++i) 
     { 
      if (obj1[i] != obj2[i])//ok for doubles if they are generated in the same way? I guess so! 
       return false; 
     } 

     return true; 
    } 

public class Dummy : IEquatable<Dummy> 
{ 
    public Dummy(string member) 
    { 
     _member = member; 
    } 

    private string _member; 


    public virtual bool Equals(Dummy other) 
    { 
     return this._member == other._member; 
    } 

    public override bool Equals(object other) 
    { 
     return EqualsHelper.secureEquals(this, other); 
    } 

} 

    static void Main(string[] args) 
    { 
     Dummy d1 = new Dummy("Hugo"); 
     Dummy d2 = new Dummy("Hugo"); 

     object d2obj = (object)d2; 

     bool ret = d1.Equals(d2obj); 
    } 

当时的想法是: d1.Equals(d2obj)调用Dummy.Equals(对象)调用EqualsHelper.secureEquals(T,obj)调用EqualsHelper.secureEquals(T,T)调用Dummy.Equals(Dummy)。

但是最后一次调用调用Dummy.Equals(object),即使所有东西都输入到T中。

我错过了什么?

PS:我知道,与更换电话:

  if (!((IEquatable<T>)obj1).Equals(obj2)) //this calls Dummy.Equals(object other)! 

的伎俩,但它为什么没有其他的工作?

回答

5

为什么:因为此处调用的方法是静态类型的,并且涉及T而没有通用约束的唯一可用的Equalsobject.Equals(object)。完全相同的IL必须能够处理每个T - C#泛型不像C++模板;不会发生每个T超载分辨率。

顺便说一句:你可能也想看看EqualityComparer<T>.Default.Equals(obj1,obj2),将处理IEquatable<T>Nullable<T>等自动:

public static bool secureEquals<T>(T obj1, object obj2) where T : class 
{ 
    return EqualityComparer<T>.Default.Equals(obj1, obj2 as T); 
} 
+0

你的意思是'EqualityComparer .Default.Equals(...)'? – 2012-01-03 09:06:45

+0

使用EqualityComparer的优势是什么? – B3ret 2012-01-03 09:11:21

+0

@Jon已更新(现在只看到评论) – 2012-01-03 09:12:59

4

EqualsHelper编译内EqualsHelper.secureEqualsEquals超载得到解决 - 和代码没有按不知道T是否执行IComparable<T>,所以剩下的就是Equals(Object)。您可以添加一个约束到T这将使它使用正确的过载:

public static bool SecureEquals<T>(T obj1, T obj2) where T : IEquatable<T> 

当然,这会限制与您可以使用它的类。

(另外,请注意,我已将secureEquals更名为SecureEquals,以符合.NET命名约定。我个人也不会在此使用“secure”这个词 - 这里没有安全敏感的地方。)

+0

谢谢,我发现它发生在我发布的那一刻... – B3ret 2012-01-03 09:09:05

0

因为在secureEquals中没有约束,编译器总是假定Object.Equals存在。为你的T添加接口约束。