这是关于我要执行的操作的一个示例:
public class Foo : IEquatable<Foo>
{
public bool Equals(Foo other)
{
Type type1 = this.GetType();
Type type2 = other.GetType();
if (type1 != type2)
return false;
if (type1 == typeof(A))
{
A a = (A)this;
A b = (A)other;
return a.Equals(b);
}
else if (type1 == typeof(B))
{
B c = (B)this;
B d = (B)other;
return c.Equals(d);
}
else
{
throw new Exception("Something is wrong");
}
}
}
public class A : Foo, IEquatable<A>
{
public int Number1 { get; set; }
public int Number2 { get; set; }
public bool Equals(A other)
{
return this.Number1 == other.Number1 && this.Number2 == other.Number2;
}
}
public class B : Foo, IEquatable<B>
{
public int Number1 { get; set; }
public int Number2 { get; set; }
public int Number3 { get; set; }
public bool Equals(B other)
{
return this.Number1 == other.Number1 && this.Number2 == other.Number2 && this.Number3 == other.Number3;
}
}
但是正如您在上面看到的那样,我必须使用许多条件'if'来标识实际类型。问题是我必须使用基类。例如:
A a = new A();
Foo foo = a;
foo.Equals(another);
最佳答案
作为您问题的直接答案,您似乎总是通过延迟(具体)子类的IEquatable<Foo>
实现来实现IEquatable<self>
。看起来像这样:
(错误代码,仅用于演示)
// You need to specify what you want when this method is called on a
// vanilla Foo object. I assume here that Foo is abstract. If not, please
// specify desired behaviour.
public bool Equals(Foo other)
{
if (other == null || other.GetType() != GetType())
return false;
// You can cache this MethodInfo..
var equalsMethod = typeof(IEquatable<>).MakeGenericType(GetType())
.GetMethod("Equals");
return (bool)equalsMethod.Invoke(this, new object[] { other });
}
但是,实际上并不清楚为什么需要相等比较才能始终“通过”基类的
IEquatable<self>
实现。该框架已经具有虚拟的
Equals
方法,该方法将导致将相等调用分派(dispatch)到适当的方法。另外,EqualityComparar<T>.Default
(大多数收集类型用于进行相等性检查的)已经可以根据需要选择IEquatable<self>.Equals(self)
或object.Equals(object)
。据我所知,试图在仅转发请求的基类中创建平等的实现,对任何东西都没有增加任何值(value)。
在无需进一步说明为什么需要基类
IEquatable<>
实现的情况下,我建议仅在每种类型上正确实现相等性。例如:public class A : Foo, IEquatable<A>
{
public int Number1 { get; set; }
public int Number2 { get; set; }
public bool Equals(A other)
{
return other != null
&& Number1 == other.Number1
&& Number2 == other.Number2;
}
public override bool Equals(object obj)
{
return Equals(obj as A);
}
public override int GetHashCode()
{
return Number1 ^ Number2;
}
}