
# C# Language Design Notes for Jan. 9th, 2019

## Agenda

1. GetAsyncEnumerator signature
2. Ambiguities in nullable array type syntax
2. Recursive Patterns Open Language Issues https://github.com/dotnet/csharplang/issues/2095

## Discussion

### Async streams GetAsyncEnumerator revisited

Discussed over email as well.

Proposal: bind `e.GetAsyncEnumerator()` and use the result, including methods
with optional parameters or `params` and extension methods.

We like the simple bind accepting optional parameters and `params`, but
extension methods are a problem. We have a number of different features that
have backwards compatibility constraints preventing them from preferring extension
methods over interface implementation. In addition, the design of extension methods
is always as a last resort and we prefer code directly from the type (including
interface implementation).

**Conclusion**

Bind a lookup, but without extension methods. After looking for the interface,
consider extension methods. Follow-up issue to deal with the difference with
simple `foreach`, which always looks for a zero-parameter method and doesn't
consider extension methods.

*Q: What about [Caller...] attributes?*

**A**: Let's do what we did for LINQ, which has to do roughly the same thing.

### Obsolete 

Do we respect the obsolete attribute in lookups in foreach, async foreach,
and pattern dispose?

**Conclusion**

Yes.

### Ambiguities in nullable array types (again)

Example:

`if (o is string[][]?(var e0, var e1, var e2) s)`

This is now ambiguous because the token after the `?` is not helpful in
resolving the ambiguity.

1. Keep the order, but address using lookahead
2. ? is a type constructor (reverse the order of brackets and question marks)
3. reverse the order of ?'s only
4. Introduce Array\<T>
```C#
Array<int[]?>
new Array<int[]?>(3)
new Array<int[]?> { new[] {1}, null, new [] {2, 3 }}
```
5. Don't allow nullability in jagged arrays

**Conclusion**

Let's try (2) and see how it works.

### Should SwitchExpressionException capture an unreified tuple input?

Yes, we think so.

### Rename deconstruct pattern to positional pattern?

Yes. The extra developer work required is worth it.

### Permit trailing comma in a switch expression?

```C#
e switch {
    1 => true,
    2 => false,
}
```

Yes, permit optional commas anywhere there are curly braces, including
switch expressions, property patterns, etc.

### Warnings for non-nullable fields that are not explicitly initialized

Scenarios that result in unnecessary warnings:

* Initialization helpers called from other constructors
* Factory methods that call constructors
* Object initializers
* Chained constructors
* Set-up/tear-down methods in test frameworks
* Reflection

Options:

0. Do nothing, keep the current behavior
1. Don't track initialization.
2. No warnings for private constructors
3. No warnings for constructors that call methods that might modify `this`
4. Track initialization debt with the class only, reporting warnings at
public entry points.
5. Track initialization debt across classes (and assemblies), reporting
warnings where the object is constructed

**Conclusion**

Let's keep option 0 for now. We're worried about silently hiding legitimate
warnings or that options 4 and 5 are too complicated or expensive to implement.