dotnet / dotnet/csharplang

Champion: Target-typed switch expression (16.3, Core 3)

Open
#2,389 33 comments 18 reactions 2 assignees Claimed by @333fred View on GitHub
Implemented Needs ECMA Spec Proposal Proposal champion
Dominant language
C#
Stars
12.7k
Forks
1.1k
Avg merge
11h 1m
Merged PRs (30d)
3

Description

- [X] Proposal added (below)
- [x] Discussed in LDM 2019-04-22
- [X] Decision in LDM (Approved for C# 8)
- [ ] Finalized (done, rejected, inactive)
- [ ] Spec'ed

@333fred asked me

> Given the following code, we cannot determine a best type for the switch expression and the code does not compile. Why can't we determine that the best type is `A`, given that's the target type of the expression?
>
> ``` c#
> class A
> {
> }
>
> class B : A
> {
> }
>
> class C : A
> {
> }
>
> class D
> {
>     void M()
>     {
>         A a = null;
>         a = a switch
>         {
>             B b => b,
>             C c => c,
>             _ => throw new System.Exception(),
>         };
>     }
> }
> ```
>
> Casting one branch to `A` fixes the code

My initial reaction was

> We use the same inference algorithm for `new []{ b, c }` and `() => { if (b) return b; else return c; }` and `c ? b : c` and `M(b, c)` where `T M(T x, T y)`.  The general philosophy is that we avoid inferring a type that wasn't one of the input types.  What if they had a common interface but not a common base class?  What if they had two common interfaces?  We just don't do that. We use "target type" only for certain conversions.  We don't have a "conversion from array creation" or "conversion from conditional expression" and similarly we won't have a "conversion from switch expression".

However, my answer was not satisfactory to either @333fred or myself.

This is a proposal to "do that".

### Proposal

Currently, a switch expression is specified to have a type that is the inferred common type of the expressions in the switch arms. It is (currently) required that there be such a common type.

Instead, I propose
1. We attempt to infer a common type among the arms of the switch expression. If there is such a common type, that is the (natural) type of the switch expression.
2. There is a *switch expression conversion* (a new implicit conversion-from-expression) from a switch expression to the type `T` if there is an implicit conversion from every arm's value expression to `T`.
3. Let `T` be the type of the switch expression, either the target type of the *switch expression conversion*, or if it was not subject to such a conversion the expression's natural type. It is an error if `T` does not exist. It is an error if a switch arm's expression cannot be implicitly converted to `T`.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.