Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现Equals以使引用相等或基于键的相等?_C# - Fatal编程技术网

C# 实现Equals以使引用相等或基于键的相等?

C# 实现Equals以使引用相等或基于键的相等?,c#,C#,我希望重写EntityBase类的Equals和GetHashCode,以支持基于引用(默认情况下)或通过实体键(如果引用不匹配)检查相等性。 代码如下: public abstract class EntityBase { protected virtual object Keys { get { return this; } } public override bool Equals(object obj) { if (Keys == this) re

我希望重写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;
        }
    }
}
//the myEntity here is contained (as reference) in myBindingSource  
var index = myBindingSource.IndexOf(myEntity);
所以我希望它能工作,但我使用的
BindingSource
表明它不工作,如下所示:

public class Entity : EntityBase {
    protected override object Keys {
        get {
             return SomeKeyProperty;
        }
    }
}
//the myEntity here is contained (as reference) in myBindingSource  
var index = myBindingSource.IndexOf(myEntity);
如果我没有为我的
EntityBase
类重写
Equals
,上面的代码会给出正确的结果,但是如果使用该重写,结果将是错误的,看起来它总是试图基于
值来查找项。我真的不明白这里出了什么问题

调试时,它甚至没有达到我在
Equals
方法中设置的断点。代码只是像一个黑匣子一样通过
IndexOf
调用运行


你能给我解释一下这里出了什么问题,并给我一些关于可能的修复方法的建议(或者甚至让我知道我想要实现的是不是可能的)。

事实上,我发布的代码运行与它应该运行的一样。我希望引用相等应该具有更高的优先级,但实际上,在集合中查找项目(如
IndexOf
)时,首先出现的将是找到的项目(如果引用不匹配,则将使用键)


它没有像我预期的那样工作的原因是,这里比较的两个都有
等于
0
。因此,如果使用基于键的相等,则应将这种情况视为不相等。我需要添加另一个属性来确定哪个值被视为null或空
。以下是我所期望的代码:

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
的值应与
键的类型完全相同,否则
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.
      }
   }
}

调整后,代码正常工作。

参考等式始终使用
=
。基于键的相等可以简单地使用比较来实现。@Oighea你说的是直接比较对象,但这里我想把逻辑放在
Equals
override中,这样一些集合会使用它,例如find indexI,我不认为这是推荐的。按照惯例,引用相等(它比键相等更强大)总是使用
=
,当它工作时,
Order#1==Custmer#1
不会返回true吗?当您必须添加越来越多的检查时,是时候重新考虑整个问题了。身份和平等是非常基本的概念,“这种情况应被视为不平等”,这表明整个想法是非常可疑的。你真的对此有一个频繁的用例吗?@HenkHolterman事实上它不是很频繁,我只是有一个对象列表,包括新添加的对象(它们的所有键都是空的/空的/零的)。新添加的实体可以等同于其他东西吗?我还没有看到超出引用质量的参数。@HenkHolterman我认为在这种情况下,相等性应该取决于它们的
,引用在这里几乎不重要。@HenkHolterman基于键的相等性的另一个例子是在使用包装类时。该类只是围绕一个实体(并通过附加道具公开更多的信息)。参考平等仍然适用于他们,而基于关键的平等应该是重要的实施。