Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# simple value based comparison of DTOs (and the GetHashCode dilema)

Tags:

c#

I know there are already a lot of discussions on GetHashCode but the advice they usually offer is not very conductive towards solving what should be a relatively simple problem...

I have a simple DTO class with a number of auto-implemented properties of various types and I would like to perform a simple value based comparisson on two instances of this class. (The main purpose being to determine in anything changed between to instances generated at different points in time.)

This can be done quite easily by adding the appropriate method. But as it happens, this is exactly what the Equals() method and the IEquatable interfaces should be for. So I thought that rather then just implementing a non-standard custom method it would make sense to implement IEquatable...

Now here comes the problem: The MSDN documentation says that in order to implement IEquatable you should also override Object.Equals(). Which makes sense. But if you override Object.Equals() you also should override HetHashCode(). Still not really a problem, I've found various discussions here on how to calculate it should you decide to.

HOWEVER both the documentation and all the discussions here that I've read say that the GetHashCode() output should remain stable and therefore it is NOT recommended to override it on mutable objects... I can understand this. (Though, let me note that I have no intention of using this class as a dictionary key, which seems to be the main concern...)

However the DTO class I have is mutable. Making it immutable would require the use of awkward constructors or static factory methods with a lot of arguments or a builder pattern and would prevent you from using the rather handy object initializer syntax. All-in-all it's really not worth the effort and the inconvenience.

So what now? I'd still like to add a method for comparing contents, but now I'm not really sure anymore what the recommended best practice is.

EDIT:

Forgot to add, that I've also seen suggestions on implementing GetHashCode based on a set of immuatable fields in your class. However as all my properties are auto-implemented and setable, technically they can all change...

UPDATE:

Thanks for the answers. So basically I don't need to worry about GetHashCode too much as long as "I know what I'm doing" - meaning that the class will not be used in a keyed collection.

Also thanks for the suggestion regarding the IEqualityComparer, I'll might give that a go.

It's a bit difficult to pick the "accepted" answer as they are all good answers, but I'll have to pick one...

like image 785
bjavor Avatar asked Oct 22 '22 00:10

bjavor


1 Answers

One could make the argument that your DTO shouldn't have any behavior at all, including an Equals or GetHashCode. If you want to compare objects of those types, use a method that you define somewhere else. That solves the problem nicely.

But assuming that you're not as strict with your DTOs, then you have to override Equals(Object). You don't necessarily have to implement IEquatable, but you can if you want. And, yes, if you override Equals(Object), then you really should override GetHashCode.

Yes, it's generally a bad idea for GetHashCode to depend on mutable fields. But if you won't be using the objects in keyed collections, then don't worry about it. Just go ahead and do what you need to do. Remember: the guidelines in MSDN are guidelines. If you know the rules and understand the risks of breaking them--and you're willing to live with the consequences--then go ahead and do it.

like image 84
Jim Mischel Avatar answered Nov 12 '22 20:11

Jim Mischel