简体   繁体   中英

Why I am getting this Resharper warning - does not override 'Object.Equals(object o) and 'Object.GetHashcode()'

I have the following class:

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

It works all fine. But it shows a resharper warning on the class. It says -

calculate value defines operator == or operator != but does not override Object.Equals(object o) and Object.GetHashcode()

The warning gets fix if I generate the code via 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);
    }

Now since this class is a legacy class, I am not sure if the above resharper generated code is fine.

Can someone please explain me why I get this warning?

Can someone please explain me why I get this warning?

Consider:

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

Do you expect b1 b2 and b3 to have the same values or different values?

What results do you get with your original code?

What results do you get with your proposed fix?

Do you now believe that your proposed fix is wrong? (You should.)

While you are looking at this code: do you notice anything deeply wrong about the implementation of == ? It says that two nulls are not equal to each other; is that right? Seems wrong to me.

Why does Resharper want you to override Equals ?

Consumers of your class are likely to assume Equals and == are semantically identical, but the C# language does not enforce this.

Is Resharper's proposed implementation acceptable?

If you use Resharper's code, Equals and == will not be semantically identical, because your existing code allows instances of CalculateToValue to be equal to instances of CalculateToMax , whereas Resharper's code does not.

How should I fix this?

  1. Write a specification for exactly what should happen. The goal is for you to actually know what your code is intended to do. For example, the specification should explain under what circumstances an instance of CalculateToMax may be equal to an instance of CalculateToValue ?
  2. Write test cases for each piece of your specification. Eric's answer provides a good starting point.
  3. Write your code.

For an example of how to follow these steps, I recommend reading Eric Lippert's Integer division that rounds up article.

What else do I need to do?

Consider implenting IEquatable .

Why else should I know.

Consumers of your class are likely to assume Equals / == are reflexive (A==A), commutative (A==B ≡ B==A), and transitive (A==B && B==C implies A==C). Probably your implementation will be reflexive and transitive without much planning on your part, but making your implementation commutative isn't really possible, since CalculateToMax is an enum.

Usually equality implementations can be simplified by following a simple template and chaining together calls to the equality operations on your primitives. Resharper is happy to auto-generate such code. Unfortunately, in your case you are comparing classes to enumerations...which is really weird.

Is there a way to make this easier?

Take a different approach entirely. I recommend against using equality operators to compare enums to classes.

As per Microsoft guidelines, when you overload operator "==" , you should also override Equals and GetHashcode .

Check here for guidelines: https://msdn.microsoft.com/en-us/library/7h9bszxx(v=vs.100).aspx

Check overall recommendations for implementing Equals : https://msdn.microsoft.com/en-us/library/336aedhh(v=vs.100).aspx

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM