I know I can avoid boxing by adding my own Equals implementation.
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 this an override as much as an overload. By the magic of the runtime it does correctly call the correct Equals()
implementation based on the type of the caller.
Why can't I override and change the parameter type to TwoDoubles
and let boxing occur by the power of the runtime on an as needed basis? Is it because C# doesn't support parameter contravariance (if that's the reason then why is it not supported...seems a small step from object o = new TwoDoubles()
)?
UPDATE
Clarification: object
is a part of the inheritance hierarchy of a struct. Why can we not 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 a TwoDouble even if said variable has been boxed into an object type.
We can override the equals method in our class to check whether two objects have same data or not.
Why we override equals() method? It needs to be overridden if we want to check the objects based on the property. For example, we want to check the equality of employee object by the id. Then, we need to override the equals() method.
Why is it important to override GetHashCode ? It s important to implement both equals and gethashcode, due to collisions, in particular while using dictionaries. if two object returns same hashcode, they are inserted in the dictionary with chaining. While accessing the item equals method is used.
You must override hashCode() in every class that overrides equals(). Failure to do so will result in a violation of the general contract for Object. hashCode(), which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.
Why can't I override and change the parameter type to TwoDoubles?
Because that would not be typesafe!
class B
{
public virtual void M(Animal animal) { ... }
}
class D : B
{
public override void M(Giraffe animal) { ... }
}
B b = new D();
b.M(new Tiger());
And now you just passed a tiger to a method that actually only takes a giraffe!
Same thing in your case. You're overriding a method that takes any object with a method that can only take a struct; that's not typesafe.
Is it because C# doesn't support parameter type contravariance?
No, it is because you are asking for parameter type covariance, which is not typesafe.
C# does not support parameter type contravariance either, but that's not what you're asking for.
You can change the parameter (overload) for Equals
, just as you've done, and boxing will occur as needed (i.e. whenever Equals(object) is called)
Because everything inherits (or implicitly via boxing) from object, you cannot stop people from being able to use Equals(object) on your type. However, by doing so, you get a boxed call.
If you are in control of the calling code, then always use your new overloaded option, i.e. Equals(TwoDouble)
Note, as one commentor already said, your code is slightly 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 has been wisely suggested, you should accomplish this same task but by using the IEquatable interface, in this case IEquatable<TwoDouble>
(note, no code change necessary from what we've done as it matches the signature)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With