这是我要做的事情的一个例子:
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);
答案 0 :(得分:4)
作为直接回答您的问题,您似乎通过始终遵循(具体)子类的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
方法,该方法将导致调度相应方法的相等调用。此外,EqualityComparar<T>.Default
(大多数集合类型用于进行等式检查)已经可以根据需要选择IEquatable<self>.Equals(self)
或object.Equals(object)
。 / p>
尝试在基类中创建一个只是转发请求的相等实现,就我所见,将 no 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;
}
}
答案 1 :(得分:1)
试试这段代码:
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;
}
}
注意:您可以使用Assert功能进行类型检查。
答案 2 :(得分:0)
一个选项是将Number1和Number2属性移动到基类,并且只比较子类的相等方法中添加到子类的成员。
class Foo
{
// move the common properties to the base class
public int Number1 { get; set; }
public int Number2 { get; set; }
public override bool Equals(object obj)
{
Foo objfoo = obj as Foo;
return
objfoo != null
// require objects being compared to be of
// the same derived type (optionally)
&& this.GetType() == obj.GetType()
&& objfoo.Number1 == this.Number1
&& objfoo.Number2 == this.Number2;
}
public override int GetHashCode()
{
// xor the hash codes of the elements used to evaluate
// equality
return Number1.GetHashCode() ^ Number2.GetHashCode();
}
}
class A : Foo, IEquatable<A>
{
// A has no properties Foo does not. Simply implement
// IEquatable<A>
public bool Equals(A other)
{
return this.Equals(other);
}
// can optionally override Equals(object) and GetHashCode()
// to call base methods here
}
class B : Foo, IEquatable<B>
{
// Add property Number3 to B
public int Number3 { get; set; }
public bool Equals(B other)
{
// base.Equals(other) evaluates Number1 and Number2
return base.Equals(other)
&& this.Number3 == other.Number3;
}
public override int GetHashCode()
{
// include Number3 in the hashcode, since it is used
// to evaluate equality
return base.GetHashCode() ^ Number3.GetHashCode();
}
public override bool Equals(object obj)
{
return this.Equals(obj as B);
}
}
答案 3 :(得分:0)
我认为派生类不应该在基类中处理。通常,“Foo”对A和B一无所知。
仍然可以使基本的IEquatable实现成为虚拟,允许A和B覆盖它并执行它们的特定相等性检查,即使相等检查和检查的实例仅可用作“Foo”或“Object”。
这会将.Equals(Foo obj)视为更具体的Object.Equals(Object obj)形式。