【问题标题】:Overriding the == operator in non-immutable types在非不可变类型中覆盖 == 运算符
【发布时间】:2011-05-31 14:38:00
【问题描述】:

MSDN Guidelines for Overloading Equals() and Operator == 状态:

默认情况下,运算符 == 测试 通过确定是否引用相等 两个参考表明相同 对象,所以引用类型不需要 实现运算符 == 以便 获得此功能。当一个类型 是不可变的,意味着数据 实例中包含的不能 更改,重载运算符 == 为 比较值相等而不是 引用相等可能很有用 因为,作为不可变对象,它们 可以认为是一样的,只要 它们具有相同的价值。 覆盖 非不可变类型中的运算符 == 是 不推荐。

谁能解释一下加粗的原因?

编辑 - 此外,该指南是否仅与 == 运算符相关,还是也适用于 Equals 方法?

【问题讨论】:

    标签: c# .net operator-overloading immutability equality


    【解决方案1】:

    我有根据的猜测是让事情像 .NET 中的内置类型一样运行,即 == 应该尽可能像引用相等一样工作,而 Equals 应该尽可能像值相等一样工作。考虑==Equals之间的实际区别:

    object myObj = new Integer(4);
    object myObj2 = new Integer(4);
    
    //Note that == is only called if the ref'd objects are cast as a type
    //overloading it.
    myObj == myObj2; //False (???)
    myObj.Equals(myObj2); //True (This call is virtual)
    
    //Set the references equal to each other -- note that the operator==
    //comparison now works.
    myObj2 = myObj;
    myObj == myObj2; //True
    myObj.Equals(myObj2); //True
    

    这种行为当然是不一致和令人困惑的,尤其是对于新程序员来说——但它展示了引用比较和值比较之间的区别。

    如果您遵循此 MSDN 指南,您将遵循重要类(例如字符串)所采用的指南。基本上——如果使用== 的比较成功,程序员就知道该比较总是会成功,只要所涉及的引用不被分配给新对象。程序员永远不必担心对象的内容不同,因为它们永远不会不同:

    //Mutable type
    var mutable1 = new Mutable(1);
    var mutable2 = mutable1;
    mutable1 == mutable2; //true
    mutable1.MutateToSomethingElse(56);
    mutable1 == mutable2; //still true, even after modification
    //This is consistent with the framework. (Because the references are the same,
    //reference and value equality are the same.) Consider if == were overloaded,
    //and there was a difference between reference and value equality:
    
    var mutable1 = new Mutable(1);
    var mutable2 = new Mutable(1);
    mutable1 == mutable2; //true
    mutable1.MutateToSomethingElse(56);
    mutable1 == mutable2; //oops -- not true anymore
    //This is inconsistent with, say, "string", because it cannot mutate.
    

    归结为该指南没有真正的技术原因——它只是为了与框架中的其他类保持一致。

    【讨论】:

      【解决方案2】:

      假设您有一个可变类型 A,并且您创建了一个或多个 A 类型的对象。如果该对象已存在于该集合中,则将一个对象添加到该集合应该会失败。

      现在假设您将一个对象添加到集合中,然后您更改它的属性以使其与集合中的另一个对象相等。您创建了一个非法状态,其中集合中有两个相等的对象。

      【讨论】:

      • 但是使用Equals 而不是== 并不能解决这个问题。
      • 另一个准则是始终同时覆盖 ==Equals()。还有getHashCoe()
      • 实际上确实如此 - Equal 在语义上是不同的。阅读两者的文档以查看差异。
      • @TomTom:但是Set 使用Equals,而不是==,用于比较,所以关于Set 变得不一致的争论无论如何都会发生。
      猜你喜欢
      • 2019-03-13
      • 2022-01-18
      • 1970-01-01
      • 2016-09-06
      • 2018-04-12
      • 1970-01-01
      • 1970-01-01
      • 2019-12-06
      • 1970-01-01
      相关资源
      最近更新 更多