Why can't we override Equals () in a value type without a box?

I know that I can avoid boxing by adding my own implementation of Equals.

public struct TwoDoubles { public double m_Re; public double m_Im; public TwoDoubles(double one, double two) { m_Re = one; m_Im = two; } public override bool Equals(object ob) { return Equals((TwoDoubles)ob); } public bool Equals(TwoDoubles ob) { TwoDoubles c = ob; return m_Re == c.m_Re && m_Im == c.m_Im; } } 

I can't call it overriding as much as overloading. By the magic of the runtime, it correctly returns the correct Equals() implementation based on the type of the caller.

Why can't I override and change the type of the parameter to TwoDoubles and let the box by the power of the runtime as needed? This is because C # does not support the parameterization of contravariance (if the reason is not supported for some reason ... it seems like a small step from object o = new TwoDoubles() )?

UPDATE
Explanation: object is part of the structure inheritance hierarchy. Why can't we specify a more derived type as a parameter to override an implementation from a less derived type? This would allow us to write:

  public override bool Equals(TwoDoubles ob) { TwoDoubles c = ob; return m_Re == c.m_Re && m_Im == c.m_Im; } 

Which should be called when the variable is TwoDouble, even if the specified variable was placed in an object of type.

+8
c #
source share
3 answers

Why can't I override and change the parameter type to TwoDoubles?

Because it will not be typeafe!

 class B { public virtual void M(Animal animal) { ... } } class D : B { public override void M(Giraffe animal) { ... } } B b = new D(); bM(new Tiger()); 

And now you just passed the tiger to a method that actually only accepts a giraffe!

The same thing in your case. You redefine a method that accepts any object using a method that can only accept a structure; what not types.

Is it because C # doesn't support parameter contravariance?

No, this is because you are requesting covariance of a parameter type that is not typical.

C # also does not support the contravariance of parameter parameters, but that is not what you are asking for.

+13
source share

You can change the parameter (overload) for Equals in the same way as you did, and boxing will happen as needed (i.e. whenever Equals (object) is called)

Since everything inherits (or implicitly through boxing) from the object, you cannot prevent people from using Equals (object) for your type. However, you get a boxing challenge.

If you control the calling code, always use your new overloaded version, i.e. Equals(TwoDouble)

Please note that, as one comment already said, your code is a bit incorrect, do this instead:

 public override bool Equals(object ob) { if (ob is TwoDoubles) return Equals((TwoDoubles)ob); else return false; } public bool Equals(TwoDoubles c) { return m_Re == c.m_Re && m_Im == c.m_Im; } 

EDIT , as was reasonably suggested, you must complete the same task, but using the IEquatable interface, in this case IEquatable<TwoDouble> (note: no code change is required from what we did as it matches the signature)

+2
source share

If this worked, as you suggested, where is public override bool Equals(TwoDoubles c) { return m_Re == c.m_Re && m_Im == c.m_Im; } public override bool Equals(TwoDoubles c) { return m_Re == c.m_Re && m_Im == c.m_Im; } was all that was needed to override the Equals(object) method, what would this code do?

 TwoDoubles td = new TwoDoubles(); object o = td; bool b = o.Equals(new object()); // Equals(object) overridden with Equals(TwoDouble) 

What should happen on line 3?

  • Should it call Equals(TwoDouble) ? If so, with what parameter? Default TwoDouble with all zeros? This violates the rules regarding equality.
  • Should it throw an exception? We correctly monitored the method signature to prevent this from happening.
  • Should it always return false? Now the compiler should know what the Equals method means, and it will have to relate to it differently than to other methods.

There is no good way to implement this, and it quickly causes more problems than it solves.

+2
source share

All Articles