C#相等运算符重写(==和!=)

本文关键字:重写 运算符 | 更新日期: 2023-09-27 18:21:45

可能重复:
如何在没有无限递归的情况下检查"=="运算符重载中的null?

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

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;

由于CCD_ 1是CCD_。

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

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

C#相等运算符重写(==和!=)

根据指南:

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

您可以使用(object)x == nullObject.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;
}

但是您还应该实现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();
}

现在y0可以简单地写:

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

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

请参阅此问题。使用Object.ReferenceEquals.

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

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
}