84 lines
3.5 KiB
Markdown
84 lines
3.5 KiB
Markdown
# C# Language Design Notes for Aug 30, 2017
|
|
|
|
***Warning: These are raw notes, and still need to be cleaned up. Read at your own peril!***
|
|
|
|
# IAsyncDisposable
|
|
|
|
`IAsyncDisposable` is sort of required, due to the way we translate `foreach`. Also it's useful in a lot of situations.
|
|
|
|
Don't take a `CancellationToken`, since when you cancel an operation you don't want to also cancel the clean-up.
|
|
|
|
Contract should be similar to `Dispose`, where you can call multiple times (sequentially) without problem.
|
|
|
|
If an enumerator (for instance) implements both sync and async, the client is only required to call one of them. The expansion of foreach will prefer sync or async naturally through the expansion.
|
|
|
|
Does the CT given to an enumerator apply during disposal? That would need to be up to the implementation. Standard guidance would be not to cancel any of what the disposal does. Advanced implementors might use the fact that the enumerator was canceled to skip some work.
|
|
|
|
# Alternative IAsyncEnumerable pattern
|
|
|
|
There's an alternative that does "explicit chunking", by asynchronously yielding synchronous enumerables, to be consumed in a nested loop.
|
|
|
|
Tests show that this is a lot more efficient than the simple design.
|
|
|
|
We are cautiously leaning in this direction. As long as we can work out iterators, which are not fully explored.
|
|
|
|
# ConfigureAwait
|
|
|
|
Can use extension methods on IAE
|
|
|
|
# foreach
|
|
|
|
Proposal to support foreach over enumera_tors_, not just enunera_bles_.
|
|
|
|
Should enumerators be first class currency? There's a path we can take where everything is still enumerables, and you can get enumerables from other enumerables representing e.g. something with a CT, a certain starting point, etc.
|
|
|
|
Downsides: If you're just foreaching over an enumerator, is it your responsibility to dispose it? Also, should LINQ then be implemented over those as well?
|
|
|
|
Let's not open that Pandora's box for now. Let's stick with enumerable.
|
|
|
|
Consider a ToEnumerable on enumerators.
|
|
|
|
## Syntax options
|
|
|
|
Need to think about it in connection with `using` also.
|
|
|
|
We'll stick with `foreach await ( ... )` for now.
|
|
|
|
## pattern-based
|
|
|
|
Similar to today. We get that one layer of optimization. There's more wrapping here (MoveNextAsync, WithCancellation), so we quickly still end up with interface dispatch.
|
|
|
|
# iterators
|
|
|
|
Same as current iterators, except with an `async` keyword, and IAsyncEnumerable/tor return type. Needs to feel exactly like putting iterators and async methods together.
|
|
|
|
Could consider custom builders for this. Skip for now.
|
|
|
|
If we do the fancier version of IAE we need to find out how to compile. Need to spec the contract completely and then follow that. (Probably some sequences of calls would be unspecified).
|
|
|
|
## Cancellation
|
|
|
|
There are two competing models around this.
|
|
|
|
1. Take CT into GetEnumerator, and find a way to syntactically expose it in an iterator body
|
|
2. Don't pass CT's into the enumerator at all; pass them to iterator methods
|
|
|
|
We actually want to start out with 2, and see if that gets us into trouble
|
|
|
|
|
|
# LINQ
|
|
|
|
There are 200 overloads on enumerable, and most would need to be duplicated on IAE. Then, mixing sync and async would add another axis of this.
|
|
|
|
Ix has an implementation of these already, and they would adjust to what we decide.
|
|
|
|
If you have that, query expressions would work to some degree, when the bodies are sync.
|
|
|
|
However, we don't currently allow `await` in query clauses, because the lambdas we target don't have the `async` modifier.
|
|
|
|
Fine to not do it now. At some point we would want to deeply investigate how to get those awaits in.
|
|
|
|
|
|
|
|
|
|
|