This MSDN article spells out when to declare a type as a value type (struct) vs a reference type (class). In particular, it says:
AVOID defining a struct unless the type has all of the following characteristics:
- It logically represents a single value, similar to primitive types (int, double, etc.).
- It has an instance size under 16 bytes.
- It is immutable.
- It will not have to be boxed frequently.
In all other cases, you should define your types as classes.
Then, this MSDN article spells out some guidelines for overriding Object.Equals() on a type, including:
When a type is immutable, ... 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. It is not a good idea to override operator == in non-immutable types.
So it seems to me, if a type is meant to be immutable, you would just declare it a struct and override ValueType.Equals(). But, if your type is declared a class, you only want reference semantics, in theory. This SO post seems to support that. So my question is, why would you ever bother overriding Equals() on a reference type? Doing so is like saying that reference semantics aren't good enough for your reference type, which makes no sense to me. The only example I can think of is if you have a large (>16 byte instances) class that has a mix of mutable and immutable fields, but even then it seems like reference semantics would be all you need.