【问题标题】:Why I am getting this Resharper warning - does not override 'Object.Equals(object o) and 'Object.GetHashcode()'为什么我收到此 Resharper 警告 - 不覆盖 'Object.Equals(object o) 和 'Object.GetHashcode()'
【发布时间】:2016-08-19 01:48:57
【问题描述】:

我有以下课程:

public class CalculateToValue
{
    public CalculateToValue(string normalValue)
    {
        NormalValue = normalValue;
    }

    public string NormalValue { get; private set; }

    public bool Equals(string other)
    {
        return NormalValue.Equals(other);
    }

    public bool Equals(CalculateToMax other)
    {
        return NormalValue.Equals(Enum.GetName(typeof(CalculateToMax),
    other));
    }

    public static bool operator ==(CalculateToValue a, CalculateToMax b)
    {
        if (((object) a == null) || ((object) b == null))
        {
            return false;
        }

        return a.Equals(b);
    }

    public static bool operator !=(CalculateToValue a, CalculateToMax b)
    {
        return !(a == b);
    }
  }

一切正常。但它在课堂上显示了一个更清晰的警告。它说-

计算值定义运算符== 或运算符!=,但不会覆盖Object.Equals(object o)Object.GetHashcode()

如果我通过 resharper 生成代码,警告会得到修复。

   protected bool Equals(CalculateToValue other)
    {
        return string.Equals(NormalValue, other.NormalValue);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((CalculateToValue) obj);
    }

现在由于这个类是一个遗留类,我不确定上面的 resharper 生成的代码是否正常。

谁能解释一下为什么我会收到这个警告?

【问题讨论】:

  • 这个想法是,如果您定义 == 运算符,您可能还希望覆盖这些方法,以指示您希望根据值而不是引用对该类的对象进行排序和比较。但是,您已经定义了具有不同类型的运算符,这本身就很奇怪。实际上,您似乎应该定义显式或隐式转换。

标签: c# resharper overloading


【解决方案1】:

谁能解释一下为什么我会收到这个警告?

考虑:

CalculateToValue ctv = whatever;
CalculateToMax ctm = whatever;
bool b1 = ctv.Equals(ctm);
bool b2 = ctv == ctm;
bool b3 = ctv.Equals((object)ctm);

您希望 b1 b2 和 b3 具有相同的值还是不同的值?

使用原始代码得到什么结果?

您提出的修复方案有何结果?

您现在是否认为您提出的解决方案是错误的? (你应该。)

当您查看此代码时:您是否注意到== 的实现有什么严重错误?它说两个空值不相等;那正确吗?对我来说似乎是错误的。

【讨论】:

  • 我很抱歉,但我不确定这段代码做了什么比较。我只是想修复 resharper 警告。我提出的修复是 resharper 在所有其他现有代码之上建议(生成)的代码。将此新代码与所有其他代码一起添加是否会产生影响?
  • @App:那么您的问题是“我想通过编写更多我不理解的不正确代码来删除我不理解的错误代码中的警告。”你这样做的顺序错误。 从深入理解代码开始,然后然后决定如何修复警告。目标不是删除警告。 目标是使代码正确
  • @App:您说代码是“工作正常”的“遗留”类。由于它充满了错误,因此我假设您的意思是(1)没有经过充分测试的类,以及(2)您不理解的类。如果代码经过充分测试,那么错误就已经被修复了,如果您理解代码,您会看到缺少哪些测试。在尝试编辑代码之前解决这两个问题。当你为这段代码写测试时,你会很快发现它有很多问题;一旦你知道问题是什么并且你理解了代码,然后修复它。
  • 非常感谢您的建议。赞赏。我将深入研究代码。
【解决方案2】:

Resharper 为什么要你覆盖Equals

您班级的消费者可能会认为 Equals== 在语义上是相同的,但 C# 语言并不强制这样做。

Resharper 提议的实现是否可以接受?

如果您使用 Resharper 的代码,Equals== 在语义上将不相同,因为您现有的代码允许 CalculateToValue 的实例等于 CalculateToMax 的实例,而 Resharper 的代码则不允许。

我应该如何解决这个问题?

  1. 为应该发生的事情写一个规范。目标是让您真正了解您的代码打算做什么。例如,规范应该解释在什么情况下CalculateToMax 的实例可能等于CalculateToValue 的实例?
  2. 为您的每一条规范编写测试用例。 Eric's answer 提供了一个很好的起点。
  3. 编写您的代码。

有关如何执行这些步骤的示例,我建议阅读 Eric Lippert 的 Integer division that rounds up 文章。

我还需要做什么?

考虑实现IEquatable

我为什么要知道。

您班级的消费者可能认为Equals/== 是自反的 (A==A)、交换的 (A==B ≡ B==A) 和传递的 (A==B && B= =C 意味着 A==C)。可能您的实现将是自反和传递的,您无需进行太多计划,但实际上不可能使您的实现具有可交换性,因为 CalculateToMax 是一个枚举。

通常可以通过遵循一个简单的模板并将对原语上的相等操作的调用链接在一起来简化相等实现。 Resharper 很乐意自动生成这样的代码。不幸的是,在您的情况下,您将类与枚举进行比较......这真的很奇怪。

有没有办法让这更容易?

完全采用不同的方法。我建议不要使用相等运算符来比较枚举和类。

【讨论】:

    【解决方案3】:

    根据 Microsoft 指南,当您重载运算符 "==" 时,您还应该覆盖 EqualsGetHashcode

    在此处查看指南: https://msdn.microsoft.com/en-us/library/7h9bszxx(v=vs.100).aspx

    检查实施Equals 的总体建议: https://msdn.microsoft.com/en-us/library/336aedhh(v=vs.100).aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-05
      • 1970-01-01
      • 2011-11-10
      • 1970-01-01
      相关资源
      最近更新 更多