【问题标题】:C# equality operators override (== and !=) [duplicate]C#相等运算符覆盖(==和!=)[重复]
【发布时间】:2012-02-21 23:09:01
【问题描述】:

可能重复:
How do I check for nulls in an ‘==’ operator overload without infinite recursion?

我有一个看起来像这样的对象:

public class Tags
{
   int mask;

   public static bool operator !=(Tags x, Tags y)
   {
      return !(x == y);
   }

   public static bool operator ==(Tags x, Tags y)
   {
      return x.mask == y.mask;
   }
}

这可以很好地用于比较实例,但我也希望能够处理如下表达式:

if(tags1 == null)

这样做会导致以下行出现异常:

return x.mask == y.mask;

因为y 是null。

我已尝试将此功能更改为:

public static bool operator ==(Tags x, Tags y)
{
   if (x == null && y == null) return true;
   if (x == null || y == null) return false;

   return x.mask == y.mask;
}

但是,这会导致堆栈溢出,因为实现使用自己的覆盖比较运算符。

让== 运算符处理与null 的比较的诀窍是什么?谢谢!

【问题讨论】:

  • 看到这个[问题][1]。 [1]:stackoverflow.com/questions/73713/…
  • @MichaelLiu:你认为究竟是什么错误?
  • 唉,我误读了答案。没有错误。我会删除我的评论。
  • @KonradRudolph 它更像是 Rohan West 的链接的副本..
  • @nawfal 我不同意。 narrow 问题在 Rohan 的链接中得到了回答,但更广泛的问题——如何在语义上正确地实现相等检查——在另一个问题中得到了广泛的回答。

标签: c# .net operator-overloading


【解决方案1】:

您可以使用(object)x == null 或Object.ReferenceEquals(x, null),而不是x == null:

public static bool operator ==(Tags x, Tags y)
{
    if ((object)x == null && (object)y == null) return true;
    if ((object)x == null || (object)y == null) return false;

    return x.mask == y.mask;
}

但你也应该实现Equals和GetHashCode:

public override bool Equals(object obj)
{
    return this.Equals(obj as Tags);
}

public bool Equals(Tags tags)
{
    return (object)tags != null && this.mask == tags.mask;
}

public override int GetHashCode()
{
    return this.mask.GetHashCode();
}

现在operator ==可以简单写成:

public static bool operator ==(Tags x, Tags y)
{
    return (object)x != null ? x.Equals(y) : (object)y == null;
}

【讨论】:

  • +1,你的第一个方法更干净
【解决方案2】:

看到这个question。使用 Object.ReferenceEquals。

【讨论】:

  • @Mike:如果第一个参数为空,则提前退出。它可能会用y == null 调用x.Equals(y),但Equals 无论如何都需要正确处理。
【解决方案3】:

根据guideline:

public static bool operator ==(Tags a, Tags b)
{
    // If both are null, or both are same instance, return true.
    if (System.Object.ReferenceEquals(a, b))
    {
        return true;
    }

    // If one is null, but not both, return false.
    if (((object)a == null) || ((object)b == null))
    {
        return false;
    }

    // Return true if the fields match:
    return a.mask == b.mask;
}

【讨论】:

  • 我认为到目前为止我最喜欢这个。而且效果很好。
  • +1 用于挖掘官方指南。
  • 很遗憾,这不是不好的代码,因为这意味着此操作要么与Equals 返回的内容不一致,要么在Equals 中有重复的实现。为避免这种情况,总是在operator == 的实现中调用Equals,同时考虑实现GetHashCode。不要有创意,总是use a correct template
  • @KonradRudolph:选项 3:从 Equals 致电 operator ==?
  • @recursive 没有从==调用Equals
【解决方案4】:

如果您可以考虑不使用运算符而是使用方法,那么您不能定义自己的扩展方法。像这样。

public static bool IsEqual(this Tags a, Tags b) 
{
    if(a == null && b == null)
       return true;
    if((a != null && b == null) || (a == null && b != null))
       return false;
    return b.mask == this.mask
}

【讨论】:

    【解决方案5】:

    Kirill 已经给出了一个很好的答案,但我使用某种改进的模式来实现运算符,包括以下列方式正确实现 Equals() 和 GetHashCode():

    public static bool operator !=(MyType first, MyType second)
    {
        return !(first == second);
    }
    
    public static bool operator ==(MyType first, MyType second)
    {
        if (ReferenceEquals(first, null)
           || ReferenceEquals(second, null))
        {
            return ReferenceEquals(first, second);
        }
    
        return first.Equals(second);
    }
    
    public override bool Equals(object obj)
    {
        return Equals(obj as MyType);
    }
    
    public bool Equals(MyType other)
    {
        if (ReferenceEquals(other, null))
        {
            return false;
        }
    
        if (ReferenceEquals(this, other))
        {
            return true;
        }
    
        // Check all simple properties
        if (GetHashCode() != other.GetHashCode()
            || Name != other.Name
            || Age != other.Age
            || Phone != other.Phone)
        {
            return false;
        }
    
        return true;
    }
    
    public override int GetHashCode()
    {
        unchecked
        {
            var hash = 34591;
    
            if (Name != null)
            {
                hash = hash * 29863 + Name.GetHashCode();
            }
    
            if (Phone != null)
            {
                hash = hash * 29863 + Phone.GetHashCode();
            }
    
            hash = hash * 29863 + Age;
    
            return hash;
        }
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多