【问题标题】:Question regarding declaration of equality operators in C#关于在 C# 中声明相等运算符的问题
【发布时间】:2018-12-30 19:47:55
【问题描述】:

这似乎非常基本,但我在这个特别的笔记上找不到任何其他答案。在 C# 中声明 == 运算符时,还必须声明 != 运算符。显然,每种情况都可能因类型而异,但如果一个类型具有显式相等或没有,那么将!= 简单地声明为!(a == b) 是否合理?有理由不这样做吗?例如:

    public static bool operator ==(Point p1, Point p2)
    {
        return ((p1.X == p2.x) && (p1.Y == p2.Y));
    }

    public static bool operator !=(Point p1, Point p2)
    {
        return !(p1 == p2);
    }

【问题讨论】:

  • 显而易见的答案是,在 x86 汇编中,a != b 在两条指令中完成(CMPJNE),而 !(a == b) 在三个指令中完成(CMP,@ 987654332@, 和NOT)
  • @RezaAghaei - 谢谢!说得通。 @Powerlord - 因为== 在这种情况下比较两个字段...这是否会使我的== 实现成为CMP CMP JNE!= 成为CMP CMP CMP JNE @ 987654343@?两次比较会是总共四次操作吗?
  • 如果两个不相等的事物不一定不相等,你就不会这样做。示例:下溢的两个计算可能既不相等,也可能不相等。 NaN、无穷大、N/As、NULL 也可能如此。
  • @DourHighArch 哦,当然 - 绝对只适用于明确的二进制相等。

标签: c# operators


【解决方案1】:

Microsoft Docs 中有一个很好的例子:How to: Define Value Equality for a Type 涵盖了定义类型相等性的重要方面。

在以下示例中,对于 x!=y,您会看到它只是返回 !(x==y)

using System;
class TwoDPoint : IEquatable<TwoDPoint>
{
    // Readonly auto-implemented properties.
    public int X { get; private set; }
    public int Y { get; private set; }

    // Set the properties in the constructor.
    public TwoDPoint(int x, int y)
    {
        if ((x < 1) || (x > 2000) || (y < 1) || (y > 2000))
        {
            throw new System.ArgumentException("Point must be in range 1 - 2000");
        }
        this.X = x;
        this.Y = y;
    }

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

    public bool Equals(TwoDPoint p)
    {
        // If parameter is null, return false.
        if (Object.ReferenceEquals(p, null))
        {
            return false;
        }

        // Optimization for a common success case.
        if (Object.ReferenceEquals(this, p))
        {
            return true;
        }

        // If run-time types are not exactly the same, return false.
        if (this.GetType() != p.GetType())
        {
            return false;
        }

        // Return true if the fields match.
        // Note that the base class is not invoked because it is
        // System.Object, which defines Equals as reference equality.
        return (X == p.X) && (Y == p.Y);
    }

    public override int GetHashCode()
    {
        return X * 0x00010000 + Y;
    }

    public static bool operator ==(TwoDPoint lhs, TwoDPoint rhs)
    {
        // Check for null on left side.
        if (Object.ReferenceEquals(lhs, null))
        {
            if (Object.ReferenceEquals(rhs, null))
            {
                // null == null = true.
                return true;
            }

            // Only the left side is null.
            return false;
        }
        // Equals handles case of null on right side.
        return lhs.Equals(rhs);
    }

    public static bool operator !=(TwoDPoint lhs, TwoDPoint rhs)
    {
        return !(lhs == rhs);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 2020-04-26
    相关资源
    最近更新 更多