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

## Agenda

1. Shadowing in lambdas
2. pattern-based disposal in `await foreach`

## Discussion

### Shadowing in nested functions

*Q: Allow shadowing for all lambdas as well?*

**A**: Yes.

*Q: Allow shadowing with range variables in LINQ queries?*

```C#
// char c;
var q = from c in s
        from c2 in s
        where c != ' '
        select c;
var q2 = s
    .SelectMany(c => s, (c, c2) => new { c, c2 })
    .Where(_x => _x.c != ' ')
    .Select(_x => _x.c);
```

`c` and `c2` can't be named the same because they are equivalent to two
parameters being named the same. However, should the new `c` be able to
shadow the local `c`?

**A**: Let's look at the implementation and decide based on the complexity.

### Pattern-based disposal in `await foreach`

`WithCancellation` and `ConfigureAwait` both return a custom type that does
not implement the interface, just the pattern. `await foreach` does not pick
it up because it does not have pattern-based disposal and the type cannot
implement the `IAsyncDisposable` type because it does not produce a `ValueTask`
return for disposal.

Proposals:

1. Just allow pattern-based disposal for `IAsyncDisposable`. Only allow
   pattern-based disposable for `IDisposable` in ref structs.

   a. For `await foreach`, use the pattern, then dynamically check for
   interface and use it if present.

   b. For `await foreach`, use the pattern, then statically check for the
   interface and use it if present.

The dynamic check in (1a) is used because in C# 1.0 the non-generic `IEnumerator`
did not implement IDisposable.

The next question is whether to consider extension methods. The standard pattern
we've previously settled on is:

1. Check for pattern
2. Check for interface
3. Check for extension methods

Can we use this pattern for `IAsyncDisposable`? The primary question is whether
to consider extension methods.

**Conclusion**

Let's do 1b. We do not have a non-generic `IAsyncEnumerator` that doesn't
implement `IAsyncDisposable`, so the dynamic check is unnecessary.

We will not consider extension methods for `IAsyncDisposable` or
`IDisposable` (on ref structs). We will consider extension methods for
`IAsyncEnumerable` and `IEnumerable`.
