解决! 这有效,我需要告诉编译器T当然实现了IEquatable ......
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(object)调用EqualsHelper.secureEquals(T,obj)调用EqualsHelper.secureEquals(T,T)调用Dummy.Equals(Dummy)。
最后一个调用会调用Dummy.Equals(object),即使所有内容都输入到那里。
我错过了什么?
PS:我知道用以下代码取代电话:
if (!((IEquatable<T>)obj1).Equals(obj2)) //this calls Dummy.Equals(object other)!
诀窍,但为什么它不起作用?
答案 0 :(得分:5)
原因:因为此处的方法调用是静态类型的,并且唯一可用的Equals
涉及没有通用约束的T
是object.Equals(object)
。完全相同的IL必须能够处理每个 T
- C#泛型不像C ++模板;没有出现per-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);
}
答案 1 :(得分:4)
编译Equals
时,EqualsHelper.secureEquals
内的EqualsHelper
重载已得到解决 - 该代码无法知道T
是否实现IComparable<T>
所以剩下的就是Equals(Object)
。您可以向T
添加约束,这将使其使用正确的重载:
public static bool SecureEquals<T>(T obj1, T obj2) where T : IEquatable<T>
当然,这会限制您可以使用它的类。
(另外,请注意我已将secureEquals
重命名为SecureEquals
以符合.NET命名约定。我也不会使用&#34; secure& #34;完全在这里 - 这里没有任何安全敏感。)
答案 2 :(得分:0)
因为在secureEquals
中没有约束,编译器总是假定存在Object.Equals。为T添加接口约束。