我想覆盖我的EntityBase类的Equals
和GetHashCode
,以支持基于引用(默认情况下)或实体键(如果引用不匹配)检查相等性。
这是代码:
public abstract class EntityBase
{
protected virtual object Keys { get { return this; } }
public override bool Equals(object obj)
{
if (Keys == this) return base.Equals(obj);
var entity = obj as EntityBase;
if (entity == null) return false;
var re = ReferenceEquals(entity, this);
return re || Equals(entity.Keys, Keys);
}
public override int GetHashCode()
{
if (Keys == this) return base.GetHashCode();
return base.GetHashCode() * 17 + (Keys?.GetHashCode() ?? 0);
}
}
现在在派生类中,它可以是这样的:
public class Entity : EntityBase {
protected override object Keys {
get {
return SomeKeyProperty;
}
}
}
所以我希望它能够正常运行,但我使用的BindingSource
表明它不起作用,就像这样:
//the myEntity here is contained (as reference) in myBindingSource
var index = myBindingSource.IndexOf(myEntity);
如果我没有覆盖Equals
类的EntityBase
,上面的代码会给出正确的结果,但是如果重写,结果将是错误的,看起来总是试图看起来对于基于Keys
值的项目。我真的不明白这里的错误。
调试时,它甚至没有达到我在Equals
方法中设置的断点。代码只是通过IndexOf
调用,就像它是一个黑盒子一样。
你能否向我解释一下这里有什么问题,并给我一些关于可能修复的建议(或者甚至让我知道我想达到的目标是否可行)。
答案 0 :(得分:0)
实际上我发布的代码就像它应该的那样运行。我希望引用相等应该具有更高的优先级,但实际上当在集合中找到一个项目(如IndexOf
)时,首先发现的是(如果引用不匹配则将使用键)
它之所以无法正常工作的原因是因为这里比较的两个都有Keys
等于0
。因此,如果使用基于密钥的相等性,则应将该情况视为unequal
。我需要添加另一个属性来确定哪个值被视为null或空Keys
。以下是我预期的代码:
public abstract class EntityBase
{
protected virtual object Keys { get { return this; } }
protected virtual object EmptyKeys {get { return null;} }
public override bool Equals(object obj)
{
if (Keys == this) return base.Equals(obj);
var entity = obj as EntityBase;
if (entity == null) return false;
var re = ReferenceEquals(entity, this);
return re || GetType() == entity.GetType() && Equals(entity.Keys, Keys) && !Equals(Keys, EmptyKeys);
}
public override int GetHashCode()
{
if (Keys == this) return base.GetHashCode();
return base.GetHashCode() * 17 + (Keys?.GetHashCode() ?? 0);
}
}
在派生类中,我们需要覆盖EmptyKeys
以指示哪个值被视为空,请注意,对于数字键(如long
,...),{{1}的值应该是EmptyKeys
的确切类型,否则Keys
将不起作用。
Equals
在调整之后,代码可以正常工作。