Actually this one is pretty obvious. But if you are focused on implementing some complex logic, it is easy to forget about this requirement. Let’s assume there is following piece of code:
This will compile and run, however it will not distinguish
ProductCodeCentreNumPair instances. I.e. it will not do the grouping, but produce a sequence of
IGroupings, each for corresponding source item. The reason is self-evident, if we try to think for a while. This custom class does not have custom equality comparison logic implemented. Default logic is based on
ReferenceEquals so, as each separate object resides at different memory address, they all will be recognized as not equal to each other. Even if they contain the same values in their fields (strings behave like value types, although they are reference types). I used the following set of overridden methods to provide my custom equality comparison logic to solve the problem. It is important to note, that
GetHashCode is also needed in order for the grouping to work.
Alternatively you can use anonymous types, I mean:
will just work. This is because instances of anonymous classes have automatically generated equality comparison logic based on values of their fields. Contrary to
ReferenceEquals based implementation generated for typical named classes. They are most frequently used in the context of comparisons, so it seems reasonable.
One more alternative is to use a structure instead of a class. But structures should only be used if their fields are value types, because only then you can benefit from binary comparison of their value. And even having
structs instead of
classes requires implementing custom
GetHashCode. By not implementing it, there is a risk that 1) the auto-generated implementation will use reflection or 2) will not be well distributed across
int leading to performance problems when adding to