C#相等运算符覆盖(==和!=)

时间:2012-01-30 03:44:24

标签: c# .net operator-overloading

  

可能重复:
  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;

由于ynull

我尝试将此功能更改为:

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的比较的诀窍是什么?谢谢!

5 个答案:

答案 0 :(得分:7)

根据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 :(得分:6)

您可以使用x == null(object)x == null代替Object.ReferenceEquals(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;
}

但您还应该实施EqualsGetHashCode

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;
}

答案 2 :(得分:0)

question。使用Object.ReferenceEquals。

答案 3 :(得分:0)

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;
    }
 }

答案 4 :(得分:-1)

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

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
}