-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: "sync" block in async/iterator methods #11308
Comments
I think #119 and #8181 are related. Perhaps these should be merged to a single feature. public int Insert(T item, int index) {
pre { guard (index >= 0 && index <= Count); }
post { guard (value >= 0 && value < Count); }
return InsertCore(item, index);
}
public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) {
pre {
guard (source != null) else throw new ArgumentNullException(nameof(source));
guard (predicate != null) else throw new ArgumentNullException(nameof(predicate));
}
foreach (var item in source) {
if (predicate(item))
yield return item;
}
}
public static async ValueTask<int> DelayWithResult(int delay) {
pre { guard (delay > 0) else return ValueTask<int>.FromValue(delay); }
await Task.Delay(delay);
return delay;
}
|
Your sync block would give me a structural way to allow async constructors. The language could enforce that all operations that must be done in a constructor, must be be done in a sync block if it's an async constructor. |
@svick As it turns out, your implementation with local functions DOES NOT defer the state machine creation in |
This reminds me a little of powershell's Here is how they do it. function Paint-Car
{
param($car)
begin {
#setup the prereqs
$paintColor = Mix-Paint("blue")
}
process {
#The loop body
echo "painting $car!"
ApplyPaint -Paint $paintColor -Car $car
}
end {
#cleanup
Cleanup-Paint -Paint $paintColor
}
}
....
List-Cars -Name Ford* | Paint-Car
|
@alrz If I understand the generated code correctly, it does defer the state machine creation. But it also allocates a closure (a.k.a. display class) as soon as the method starts, so it does not avoid allocation as I was indeed assuming. |
@playsomethingsaxman I don't understand how would |
@svick You are right, it's a separate class, but there will be an allocation anyways. |
@svick Watch:
By the way, why did they gut async set? |
@playsomethingsaxman But how do you Also, |
The constructor isn't to be awaited, if you need that then there's the static factory method pattern. It simply continues initialization without having to call a separate dangling async method that also has the danger of being called again by other class members. I've built epicly scaleable code with constructs like SwitchTo() because intent just flows so much better and faster. Everyone else is just shooting themselves in the foot with dogma. You can't crank serious code out with Task.Run(). And the .NET Framework thread pool is pure crap anyway, no offense. I've seen it crack and shatter embarrassingly with my butt on the line. It doesn't scale to anything, and people get around it by throwing more servers at the problem. I think that's the real reason for .NET Core, to secretly rewrite the crap, I don't think anyone says it out loud, lol |
I would love to see async constructors return |
Issue moved to dotnet/csharplang #1217 via ZenHub |
A relatively common request is to do something in a state machine method (i.e.
async
method or iterator method) before the state machine is created, either for efficiency (common withasync
) or for correctness (common with iterators).In C# 7, these cases can be solved fairly well with local functions (the second example uses arbitrary async returns #10902):
My proposal is to make this even nicer, by including a
sync
block at the start of the method that contains the code that should execute before the state machine is created. Also, if thesync
block returns or throws, the result is returned or thrown directly, without wrapping inTask
, tasklike, orIEnumerable<T>
.This means the examples above become:
This is similar to Defer async state machine creation #10449, except that it's explicit. Being explicit has both advantages (the change of semantics regarding what happens to thrown exceptions is allowed) and disadvantages (the optimization doesn't happen automatically).
The keyword
sync
is not ideal: it's not currently a keyword and could be confusing for iterator methods. Suggestions for alternative syntax are welcome.The text was updated successfully, but these errors were encountered: