Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
975 views
in Technique[技术] by (71.8m points)

c# - ref and out arguments in async method

Does anyone know why async methods are not allowed to have ref and out arguments? I've done a bit of research on it but the only thing I could find was that it has to do with the stack unrolling.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Does anyone know why async methods are not allowed to have ref and out arguments?

Sure. Think about it - an async method usually returns almost immediately, long before most of the actual logic is executed... that's done asynchronously. So any out parameters would have to be assigned before the first await expression, and there'd quite possibly have to be some restriction on ref parameters to stop them from being used after the first await expression anyway, as after that they may not even be valid.

Consider calling an async method with out and ref parameters, using local variables for the arguments:

int x;
int y = 10;
FooAsync(out x, ref y);

After FooAsync returns, the method itself could return - so those local variables would no longer logically exist... but the async method would still effectively be able to use them in its continuations. Big problems. The compiler could create a new class to capture the variable in the same way that it does for lambda expressions, but that would cause other issues... aside from anything else, you could have a local variable changing at arbitrary points through a method, when continuations run on a different thread. Odd to say the least.

Basically, it doesn't make sense to use out and ref parameters for async methods, due to the timing involved. Use a return type which includes all of the data you're interested in instead.

If you're only interested in the out and ref parameters changing before the first await expression, you can always split the method in two:

public Task<string> FooAsync(out int x, ref int y)
{
    // Assign a value to x here, maybe change y
    return FooAsyncImpl(x, y);
}

private async Task<string> FooAsyncImpl(int x, int y) // Not ref or out!
{
}

EDIT: It would be feasible to have out parameters using Task<T> and assign the value directly within the method just like return values. It would be a bit odd though, and it wouldn't work for ref parameters.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...