Proposal equatable and comparable implementation #573
Replies: 13 comments
-
This is something that can easily be handled with anonymous types or tuples (define the fields that are in the comparison there, and have the anonymous type/tuple handle the call to Equals/GetHashCode). I agree that having consistency with ==, !=, etc isn't great, but is it that big of a deal to warrant a new feature in the language? I don't see it being that much of an issue, frankly. You could easily create an IEqualityComparer that takes a proxy type that handles the calls to Equals/GetHashCode (and I'd even argue this is how you should be handling custom equals implementations anyways). |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
@casperOne I've blogged about using ValueTuple to implement this, but the code is still non-trivial for reference types, handling all the null conditions correctly. Regardless, such ideas do nothing to help with the average developer who very commonly codes this incorrectly. @bondsbw The problem there is that record types will always include this functionality, which I get from a functional point of view, but from an OO point of view I'm not at all convinced that's appropriate. In any case, it requires using records instead of plain classes or structs. |
Beta Was this translation helpful? Give feedback.
-
Records are just translated to classes or structs. I think the idea is that you can override any part that is automatically implemented. |
Beta Was this translation helpful? Give feedback.
-
@bondsbw Override, not exclude. There's an important difference. |
Beta Was this translation helpful? Give feedback.
-
Assuming it's ever implemented, this feature could be implemented through source generators. |
Beta Was this translation helpful? Give feedback.
-
@wekempf If you exclude |
Beta Was this translation helpful? Give feedback.
-
@bondsbw Either records are IComparable, in which case there's a need to exclude that and just be IEquatable, or they aren't, in which case there's a need to add IComparable. The existence of records won't change the desire for this feature. |
Beta Was this translation helpful? Give feedback.
-
Sure, my previous comment is only in regard to |
Beta Was this translation helpful? Give feedback.
-
But the suggestion is about both. :) |
Beta Was this translation helpful? Give feedback.
-
What I'm saying is, there is no need for |
Beta Was this translation helpful? Give feedback.
-
I don't think it does cover it. It's an all or nothing concept with records. It "sort of" covers it as long as comparable isn't in play, but it doesn't cover it if comparable is in play. Just saying records are comparable doesn't work, as I noted. Records are basically syntactic sugar. They implement things you could have implemented yourself. You can even replace the automatically implemented features by adding your own implementations. All great. What you can't do is opt out of any features provided. It's all or nothing. Even without comparable, what do I do if I want a type that's equatable but doesn't support deconstruction? Or it's not immutable, so |
Beta Was this translation helpful? Give feedback.
-
I think Source Generators cover this sufficiently @wekempf |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Just saw the "future of C#" session from //Build 2017, and it was great to see IDE support for the implementation IEquatable/IComparable. But, frankly, this deserves language support. A rough outline of the idea, syntax very much open to debate:
The
is equatable
line causes the class to beIEquatable<Money>
and provides default implementations forEquals(Money)
,Equals(object)
andGetHashCode()
as well as==
and!=
operators. If a user supplies any of these methods in the code, then the compiler doesn't generate them. The parenthetical list portion defines what data to use in the implementation, and is optional. If the list isn't specified then all of the fields are used. For example:In this example both X and Y are used to define equality and to generate the hash code.
In addition to
is equatable
you can useis comparable
.is comparable
should implyis equatable
(whether or not it's an error to declare both is something to consider).Equality and collation in .NET are actually really hard to get right. Most classes I've seen that try get this wrong. This is precisely why the compiler (and not the IDE) should do the heavy lifting for us here. Ruby is a great example of this concept, where they have the "spaceship operator"
<=>
that is the only thing you have to define to get everything.With this in place, the compiler could also emit warnings (even if just from analyzers) for things like using mutable state in the definition of equality, further helping developers not make what is today a very common mistake.
Beta Was this translation helpful? Give feedback.
All reactions