这是我尝试做的一个例子:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
但正如你在上面所看到的,我必须使用许多条件'if'来识别真实类型.问题是我必须使用基类.例如:
A a = new A();
Foo foo = a;
foo.Equals(another);
Run Code Online (Sandbox Code Playgroud)
作为您的问题的直接答案,您似乎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 });
}
Run Code Online (Sandbox Code Playgroud)
但是确实不清楚为什么需要相等比较来始终“通过”基类的IEquatable<self>
实现。
该框架已经具有Equals
将导致将相等调用分派到适当方法的虚拟方法。此外,EqualityComparar<T>.Default
(大多数集合类型使用它来进行相等性检查)已经有选择IEquatable<self>.Equals(self)
或object.Equals(object)
适当的智慧。
就我所见,试图在只转发请求的基类中创建相等性的实现对任何东西都没有任何价值。
没有进一步解释为什么需要基类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;
}
}
Run Code Online (Sandbox Code Playgroud)
试试这段代码:
public class Foo : IEquatable<Foo>
{
public virtual bool Equals(Foo other)
{
return true;
}
}
public class A : Foo,IEquatable<A>
{
public int Number1 { get; set; }
public int Number2 { get; set; }
public override bool Equals(Foo other)
{
if (other.GetType() == typeof(A))
{
return Equals((A)other);
}
throw new InvalidOperationException("Object is not of type A");
}
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 override bool Equals(Foo other)
{
if (other.GetType() == typeof(B))
{
return Equals((B)other);
}
throw new InvalidOperationException("Object is not of type B");
}
public bool Equals(B other)
{
return this.Number1 == other.Number1 && this.Number2 == other.Number2 && this.Number3 == other.Number3;
}
}
Run Code Online (Sandbox Code Playgroud)
注意:您可以使用断言功能来进行类型检查。