c# - 实现 Equals 以使引用相等或基于键的相等?
问题描述
我想覆盖我的 EntityBase 类的Equals
andGetHashCode
以支持基于引用(默认情况下)或实体键(以防引用不匹配)检查相等性。这是代码:
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
一个黑盒子一样通过调用运行。
您能否向我解释这里出了什么问题,并就可能的解决方法给我一些建议(或者甚至让我知道我想要实现的目标是否可行)。
解决方案
实际上,我发布的代码就像它应该运行的那样运行。我希望引用相等应该具有更高的优先级,但实际上IndexOf
在集合中查找项目(如 )时,首先找到的将是找到的(如果引用不匹配,则将使用键)。
它没有按我预期工作的原因是因为这里比较的 2 个都Keys
等于0
. 因此,如果使用基于键的相等性,则应将这种情况视为unequal
. 我需要添加另一个属性来确定哪个值被视为 null 或 empty 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
,...),值EmptyKeys
应该是与 的确切类型Keys
,否则Equals
将不起作用。
public class Entity : EntityBase {
protected override object Keys {
get {
return SomeKeyProperty;//suppose this is a long property
}
}
protected override object EmptyKeys {
get {
return 0L;//here 0 value should also be a long value.
}
}
}
调整后,代码按预期工作。
推荐阅读
- azure - 多个安装了 Azure Antivirus 的 VM 需要使用 Peeklock 模型订阅 Azure 消息队列
- php - 如何在 Laravel 框架中使用列别名处理两个 whereRaw 条件?
- sql - 如何在下一个字段金额中添加余额,每个供应商名称,每个月/年
- ios - SwiftUI 与 List 元素崩溃
- c# - 为实体框架查询使用单独的类文件(模型)而不是在控制器本身中编写
- javascript - 如何将变量分配给具有特定索引的拆分字符串?
- python - 写回xml文件时toprettyxml()不起作用
- python - 使用 Selenium 和 Python 上传文件到 shopify
- javascript - 比较两个自定义格式日期jquery
- regex - 如何仅提取两个模式之间匹配的第一次出现