Overloaded operator arguments always null - c#

So I have a class which overrides Equals(object obj) and GetHashCode() along with implementing IEquatable. To make working with this type a little more natural when checking for equality I thought, heck, I'd overload the equality operator and inequality operator, no worries...
Uh oh, worries... consider the following - where both myType instances are NOT null:
if (myType != container.myType) //NullReferenceException
{
//never get here
}
//never get here either
Now, container is just another class to hold an instance of myType among other things which is used for caching items.
Here's the actual (relevant) code from myType:
public class MyType : IEquatable<MyType>
{
public static bool operator ==(MyType myTypeA, MyType myTypeB)
{
return myTypeA.Equals(myTypeB);
}
public static bool operator !=(MyType myTypeA, MyType myTypeB)
{
return !(myTypeA == myTypeB);
}
public override bool Equals(object obj)
{
if (obj != null && obj is MyType)
{
return Equals((MyType)obj);
}
return false;
}
public bool Equals(MyType other)
{
if (other != null)
{
return other.ToString() == ToString();
}
return false;
}
}
Any experience on this front?
Thanks.

Couple of pointers -
If you've overridden == and != on classes, make sure to use ReferenceEquals to check for null inside the overload implementations rather than ==, as that will call your overloaded operator and either go into a loop or try to call Equals on a null this reference, which is probably what is happening here.
Don't override == and != on classes. Those operators are meant for value equality, and classes aren't really designed to have value equality. Either remove the operator overloads, or make MyType a struct.

Tricky one... the problem is that you use the equality operator inside the Equal override as follows:
public bool Equals(MyType other)
{
if (other != null)
It goes to your overloaded != operator, which in turn goes to your == operator, which trying to do null.Equals...

As the others have stated you need to be carefull checking for nulls as it will call your equality function again, normally resulting in a StackOverflowException.
When I use the IEquatable interface on classes I normally use the following code:
public override bool Equals(object obj)
{
// If obj isn't MyType then 'as' will pass in null
return this.Equals(obj as MyType);
}
public bool Equals(MyType other)
{
if (object.ReferenceEquals(other, null))
{
return false;
}
// Actual comparison code here
return other.ToString() == this.ToString();
}

Related

Why doesn't Contains call CompareTo nor Equals?

While comparing instances of a custom class, I noticed that a call to Contains doesn't work the way I expect it to. Assuming that the default comparison goes by the reference (pointer or whatever it's called), I implemented both CompareTo and Equals. I made sure to be implementing IComparable, of course.
It's still doesn't work and I get no hits when I put breakpoints on those methods.
What can I be missing and is the best option to use extension methods if I'm not?
public override bool Equals(Object input)
{
return Id == ((MyType) input).Id;
}
public int CompareTo(Object input)
{
return Id - ((MyType)input).Id;
}
A better implementation could be:
public bool Equals(MyType other)
{
// if 'other' is a null reference, or if 'other' is more derived or less derived
if ((object)other == (object)null || other.GetType() != GetType())
return false;
// OK, check members (assuming 'Id' has a type that makes '==' a wise choice)
return Id == other.Id;
}
public override bool Equals(object obj)
{
// call to other overload
return Equals(obj as MyType);
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
You can mark the class as implementing IEquatable<MyType> in that case (but it will work even without that).
Regarding GetHashCode: Always remember to override it. You should have seen a compiler warning that it was problematic to override Equals(object) without overriding GetHashCode. Never keep the code return base.GetHashCode() in the override (assuming the base class is System.Object). Either give it a try and implement something based on the members that participate in Equals. If you do not think GetHashCode will actually be used in your case, say:
public override int GetHashCode()
{
throw new NotSupportedException("We don't have GetHashCode, sorry");
}
If you absolutely know that you will only be using List<>.Contains, and not e.g. Dictionary<,>, HashSet<> and not Linq's Distinct(), etc. etc., it could work with GetHashCode() simply throwing.
IComparable<MyType> is not needed unless you sort List<MyType> or MyType[], or you use Linq's OrderBy with MyType, or you use SortedDictionary<,>, SortedSet<>.
Overloading operator == is not needed for these uses.

Difference between string.GetHashCode and IEqualityComparer<string>.Default.GetHashCode

I would like to use Distinct() with my data, declared as IEnumerable<KeyValuePair<IdentType, string>>. In this case, i have to implement my own IEqualityComparer and there is my question:
Is there any difference between below implementations?
public int GetHashCode(KeyValuePair<IdentType, string> obj) {
return EqualityComparer<string>.Default.GetHashCode(obj.Value);
}
and
public int GetHashCode(KeyValuePair<IdentType, string> obj) {
return obj.Value.GetHashCode();
}
There is only a small difference between your two methods.
EqualityComparer<string>.Default will return a class of type GenericEqualityComparer<T> if the class implments IEquateable<T> (which string does). So that GetHashCode(obj.Value) gets called to
public override int GetHashCode(T obj) {
if (obj == null) return 0;
return obj.GetHashCode();
}
which is the same as you calling obj.Value.GetHashCode(); directly, except for the fact that if you have a null string the default comparer will return 0 and the direct call version will throw a null reference exception.
Just one: the equality comparer's GetHashCode will return 0 if the string is null, whereas the second implementation will throw an exception.
One difference is that EqualityComparer<string>.Default.GetHashCode would not crash when you pass null to it.
using System;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
var n = EqualityComparer<string>.Default.GetHashCode(null);
Console.WriteLine(n);
}
}
Other than that, the results would be identical by design, because System.String implements IEquatable<System.String>
The Default property checks whether type T implements the System.IEquatable<T> generic interface and, if so, returns an EqualityComparer<T> that invokes the implementation of the IEquatable<T>.Equals method. Otherwise, it returns an EqualityComparer<T>, as provided by T.
No. It doesn't. The implementation will be the same since they both call GetHashCode() on the actual class, in this case string.
In the end, the CreateComparer method inside the EqualityComparer creates an GenericEqualityComparer, and the implementation of it's GetHashCode is:
public override int GetHashCode(T obj) {
if (obj == null) return 0;
return obj.GetHashCode();
}
In this case, obj will be the original string where you would otherwise call GetHasCode on. The only case that will make it behave differently is when your string is null.

Equality comparing objects

I have code like this:
public bool AreSame(CreditProposal creditProposal)
{
if (!ContractingParty.Equals(creditProposal.ContractingParty))
return false;
if (!UltimateParent.Equals(creditProposal.UltimateParent))
return false;
if (!Rebound.Equals(creditProposal.Rebound))
return false;
if (!ContactPerson.Equals(creditProposal.ContactPerson))
return false;
if (!DateOfVisit.Equals(creditProposal.DateOfVisit))
return false;
.... and so on 10 more times
Is there a way to do this more concise? Or will that mean I get into reflection hell?
Override Equals method.
Check this on MSDN
And notice If you implement ==, you must implement !=.
The instinctive way to handle this situation is to override the Object.Equals(Object) method and implement IEquatable<T> for your type.
However, overriding Object.Equals will prompt you to also override Object.GetHashCode(), which is a lot harder to do correctly. Most notably, GetHashCode() must return the same value each time it is called on the same instance, and must return the same value for two objects which are considered equal. If your type is mutable, this becomes a real pain. (In fact, GetHashCode() is so difficult to implement correctly, there's a whole tag for it on StackOverflow: https://stackoverflow.com/questions/tagged/gethashcode)
The static implementation for Equals usually looks like this:
public static bool Equals(CreditProposal proposalA, CreditProposal proposalB)
{
// Check whether both values are null.
if(object.ReferenceEquals(proposalA, null)
&& object.ReferenceEquals(proposalB, null))
{
return true;
}
// Check whether either value is null.
if(object.ReferenceEquals(proposalA, null)
|| object.ReferenceEquals(proposalB, null))
{
return false;
}
// Check whether hashcodes are different.
if(proposalA.GetHashCode() != proposalB.GetHashCode())
{
return false;
}
// Check for value equality.
return Party.Equals(
proposalA.ContractingParty,
proposalB.ContractingParty)
&& ParentProposal.Equals(
proposalA.UltimateParent,
proposalB.UltimateParent);
// Add more conditions for equality here.
}
You would call this implementation from all your instance methods.

Using == operator for class type operands

I would like to be sure. If I apply == operator between two operands of type class, it returns true when both variables points at the same object?
Also like in string class, to check equality based on e.g. some value, I would need to override that operator. IS that true?
Yes, == operator compares if the references point to the same object.
In strings, it compares eqality (unlike in Java)
The default implementation of == uses referential equality on reference types, i.e. objects are equal if and only if they are the same instance.
You can overload the == and != operator. If you do that, for consistency you should also override Equals and GetHashCode(). If you don't also override those you will only get the correct equality using == and != but many other uses such as Dictionary or HashSet will still use referential equality.
You always need to overload == and != together. Usually I write the comparison itself in == and express the other comparisons using ==.
public static bool operator ==(MyClass x, MyClass y)
{
}
public static bool operator !=(MyClass x, MyClass y)
{
return !(x==y);
}
public override bool Equals(object obj)
{
if((obj==null)||(obj.GetType()!=typeof(MyClass))
return false;
return this==(MyClass)obj;
}
public override int GetHashCode()
{
}
And you should consider making the class immutable. Equality mustn't change while the object is inside a HashSet or Dictionary, and making it completely immutable saves a lot of trouble. And since you can only achieve value semantics using immutable classes and the goal of overriding equality is getting value semantics you basically need immutability.
For the second question, to give == a special meaning, you do indeed need to overload (not override) the operator (and != at the same time):
public class Test
{
public static bool operator ==(Test t1, Test t2)
{
// Insert logic here, being careful of the possibility of
// t1 and t2 being null. And don't just use if (t1 == null)
// - it will recurse!
}
public static bool operator !=(Test t1, Test t2)
{
// Usual way of implementing
return !(t1 == t2);
}
}
If you're overloading == you should almost certainly also:
Implement IEquatable<T>
Quite possibly make your class sealed and immutable (equality which can change is troubling)
Override Equals(object) and GetHashCode
== will return true for instances x and y if:
x and y are the of the same type
x and y are either the same instance, or the type that they represent has overloaded the == operator and they compare as equal according to that.
This is a full explanation from MSDN.
And yes it does compare references of class/object instances.

What are the best practices for implementing the == operator for a class in C#?

While implementing an == operator, I have the feeling that I am missing some essential points.
Hence, I am searching some best practices around that.
Here are some related questions I am thinking about:
How to cleanly handle the reference comparison?
Should it be implemented through a IEquatable<T>-like interface? Or overriding object.Equals?
And what about the != operator?
(this list might not be exhaustive).
I would follow Microsoft's Guidelines for Overloading Equals() and Operator ==.
edit: Microsoft's guidelines contain this important remark, which seems to confirm Henk's answer:
By default, the operator == tests for reference equality by
determining if two references indicate the same object, so reference
types do not need to implement operator == in order to gain this
functionality. When a type is immutable, meaning the data contained in
the instance cannot be changed, overloading operator == to compare
value equality instead of reference equality can be useful because, as
immutable objects, they can be considered the same as long as they
have the same value. Overriding operator == in non-immutable types is
not recommended
Each time you implement the == operator, be sure to also implement !=, IEquatable<T> and to override Object.Equals() and Object.GetHashCode() for consistency for the user of your class.
Considering a class, here's my usual implementation:
public bool Equals(MyClass other) {
if (ReferenceEquals(other, null))
return false;
if (ReferenceEquals(other, this))
return true;
return // your equality code here
}
public override bool Equals(object obj) {
return Equals(obj as MyClass);
}
public override int GetHashCode() {
return // your hash function here
}
public static bool operator ==(MyClass left, MyClass right) {
return Equals(left, right);
}
public static bool operator !=(MyClass left, MyClass right) {
return !(left == right);
}
If you implement ==, override .Equals and . GetHashCode
implement != as well
Check for null references using object.ReferenceEquals otherwise the operator will recurse
The most common approach is not to handle it. The default is reference comparison which in general is right for class objects.
So first you want to be very sure you need value-type behaviour.

Categories

Resources