This would have a little less syntactic overhead, which is practical. However, there are downsides:
- I can't implement a type-safe IEquatable<> anymore.
- I'd need to resolve the equalitycomparers per-instance and not per type since there'd be only one type - ValueObject. That means constructing such types would need a thread-safe dictionary lookup (imposing a little perf overhead), and every object would be one reference larger - the reference to the comparer. Furthermore, calls to GetHashCode/Equals would be one pointer indirection further away, which will also cause performance to drop. I'd expect this to be competitive with Tuple<>'s implementation, and still significantly faster than ValueType's.
- Alternatively, I could postpone the comparer lookup to GetHashCode/Equals time, but that means they'd be even slower although I'd avoid penalizing instance creation and avoid the extra object size.
This would have a little less syntactic overhead, which is practical. However, there are downsides: