Is this bad programming practice?
Implementing IEquatable<T>
is great, even more so for structs, but merely doing that much is not enough.
I've read that I also need to implement Object.Equals
Read it here why..
and Object.GetHashCode as well, but I am not sure why.
Read it here and here. Seriously, these have been discussed so many times, and it is pretty simple.. In short, you need it for collection types that deals with hashes like Dictionary<,>
or HashSet<>
I want to be able to check that an instance of MyClass is not already contained in a generic list of type MyClass. Why does the framework only suggests that you implement Equals only?
Depends on the collection type. For a List<T>
, it will check equality merely based on how you have defined Equals
method, say for Contains
method. For most scenario you will need Equals
only. But if you have a HashSet<T>
then absence and presence checks will utilize hash of your objects. Framework indeed asks us to implement good hashing approaches (without re-inventing the wheel) at appropriate places.
Any help would be greatly appreciated.
Do as below, but you have to overload operators ==
and !=
only if it make sense to you. Seeing your class I assumed its ok to have value semantics for your class. Otherwise just ignore that part (if ==
should mean reference equality)... Getting hashcode from your guid would suffice, provided that is all you need to test equality.
public sealed class MyClass : IEquatable<MyClass>
{
Guid m_id = Guid.NewGuid();
public Guid Id { get { return m_id; } }
public bool Equals(MyClass other)
{
if (ReferenceEquals(this, other))
return true;
if (ReferenceEquals(null, other))
return false;
return Id == other.Id;
}
public override bool Equals(object obj)
{
return Equals(obj as MyClass);
}
public static bool operator ==(MyClass lhs, MyClass rhs)
{
if (ReferenceEquals(lhs, null))
return ReferenceEquals(rhs, null);
return lhs.Equals(rhs);
}
public static bool operator !=(MyClass lhs, MyClass rhs)
{
return !(lhs == rhs);
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
To not get it wrong, make use of the snippet available here: For a good overview see this SO thread.