50 lines
2.7 KiB
Markdown
50 lines
2.7 KiB
Markdown
# C# Language Design Notes for Jan 17, 2017
|
|
|
|
## Agenda
|
|
|
|
A few C# 7.0 issues to review.
|
|
|
|
1. Constant pattern semantics: which equality exactly?
|
|
2. Extension methods on tuples: should tuple conversions apply?
|
|
|
|
# Constant pattern semantics
|
|
|
|
[Issue #16513](https://github.com/dotnet/roslyn/issues/16513) proposes a change to the semantics of constant patterns in `is` expressions. For the code
|
|
|
|
``` c#
|
|
e is 42
|
|
```
|
|
|
|
We currently generate the call `object.Equals(e, 42)` (or equivalent code), but we should instead generate `object.Equals(42, e)`.
|
|
|
|
The implementation of `object.Equals` does a few reference equality and null checks, but otherwise delegates to the instance method `Equals` of its *first* argument. So with the current semantics the above would call `e.Equals(42)`, whereas in the proposal we would call `42.Equals(e)`.
|
|
|
|
The issue lists several good reasons, and we can add more to the list:
|
|
|
|
- The constant pattern isn't very *constant*, when it's behavior is determined by the non-constant operand!
|
|
- Optimization opportunities are few when we cannot depend on known behavior of calling `c.Equals` on a constant value.
|
|
- Intuitively, the pattern should do the testing, not the object being tested
|
|
- Calling a method on the expression could cause side effects!
|
|
- The difference from switch semantics is jarring
|
|
- Switching would preserve the nice property of `is` expressions today that it only returns `true` if the left operand is implicitly convertible to the (type of the) right.
|
|
|
|
There really is no downside to this, other than the little bit of work it requires to implement it.
|
|
|
|
## Conclusion
|
|
|
|
Do it.
|
|
|
|
|
|
# Extension methods on tuples
|
|
|
|
[Issue #16159](https://github.com/dotnet/roslyn/issues/16159) laments the facts that extension methods only apply to tuples if the tuple types match exactly. This is because extension methods currently only apply if there is an *identity, reference or boxing conversion* from the receiver to the type of the extension method's first parameter.
|
|
|
|
The spirit of this rule is that if it applies to a type or its bases or interfaces, it will work. We agree that it *feels* like it should also work for tuples - at least "sometimes". We cannot make it just always work for tuple conversions, though, since they may recursively apply all kinds of conversions, including user defined conversions.
|
|
|
|
We could check *recursively* through the tuple type for "the right kind of conversion". Compiler-wise this is a localized and low-risk change. It makes tuples compose well with extension methods. It's another place where things should "distribute over the elements" of the tuple.
|
|
|
|
This is a now-or-never kind of change. It would be a breaking change to add later.
|
|
|
|
## Conclusion
|
|
|
|
Try to do it now if at all possible.
|