为什么我收到此Resharper警告 - 不会覆盖' Object.Equals(对象o)和' Object.GetHashcode()'

时间:2016-08-18 16:02:11

标签: c# resharper overloading

我有以下课程:

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

一切正常。但它显示了课堂上的一个resharper警告。它说 -

计算值定义运算符==或运算符!=,但不会覆盖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生成的代码是否正常。

有人可以解释一下我为什么会收到这个警告吗?

3 个答案:

答案 0 :(得分:4)

  

有人可以解释一下我为什么会收到这个警告吗?

考虑:

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

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

您的原始代码会得到什么结果?

您提出的解决方案会得到什么结果?

您现在相信您提出的解决方案是错误的吗? (你应该。)

在您查看此代码时:您是否注意到==的实现存在严重错误?它说两个零点彼此不相等;是对的吗?对我来说似乎不对。

答案 1 :(得分:2)

  

为什么Resharper要你覆盖Equals

您班级的消费者可能认为Equals==在语义上是相同的,但C#语言并未强制执行此操作。

  

Resharper的拟议实施是否可以接受?

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

  

我该如何解决这个问题?

  1. 写下准确应该发生什么的规范。目标是让您真正了解您的代码的目的。例如,规范应解释在什么情况下CalculateToMax的实例可能等于CalculateToMax的实例?
  2. 为每个规范编写测试用例。 Eric's answer提供了一个很好的起点。
  3. 编写代码。
  4. 有关如何执行这些步骤的示例,我建议您阅读Eric Lippert的Integer division that rounds up文章。

      

    我还需要做什么?

    考虑实施IEquatable

      

    为什么我应该知道。

    您班级的消费者可能认为CalculateToValue / Equals是反身的(A == A),可交换的(A ==B≡B== A)和传递(A == B& B == C意味着A == C)。可能你的实现将是自反性和传递性的,而不需要你做太多的计划,但是由于==是一个枚举,因此实现交换是不可能的。

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

      

    有没有办法让这更容易?

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

答案 2 :(得分:1)

根据Microsoft指南,当您重载运算符Equals时,您还应该覆盖GetHashcodeEquals

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

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