How to write an async method with out parameter?

How to write an async method with out parameter?

I want to write an async method with an out parameter, like this:

public async void Method1()
{
    int op;
    int result = await GetDataTaskAsync(out op);
}

How do I do this in GetDataTaskAsync?

 

回答1

You can't have async methods with ref or out parameters.

Lucian Wischik explains why this is not possible on this MSDN thread: http://social.msdn.microsoft.com/Forums/en-US/d2f48a52-e35a-4948-844d-828a1a6deb74/why-async-methods-cannot-have-ref-or-out-parameters

As for why async methods don't support out-by-reference parameters? (or ref parameters?) That's a limitation of the CLR. We chose to implement async methods in a similar way to iterator methods -- i.e. through the compiler transforming the method into a state-machine-object. The CLR has no safe way to store the address of an "out parameter" or "reference parameter" as a field of an object. The only way to have supported out-by-reference parameters would be if the async feature were done by a low-level CLR rewrite instead of a compiler-rewrite. We examined that approach, and it had a lot going for it, but it would ultimately have been so costly that it'd never have happened.

A typical workaround for this situation is to have the async method return a Tuple instead. You could re-write your method as such:

public async Task Method1()
{
    var tuple = await GetDataTaskAsync();
    int op = tuple.Item1;
    int result = tuple.Item2;
}

public async Task<Tuple<int, int>> GetDataTaskAsync()
{
    //...
    return new Tuple<int, int>(1, 2);
}

评论

Far from being too complex, this could produce too many problem. Jon Skeet explained it very well here stackoverflow.com/questions/20868103/…

Apr 21, 2015 at 13:21

I think Named Tuples in C# 7 will be the perfect solution for this.
– orad
Mar 17, 2017 at 21:56

 

回答2

The C#7+ Solution is to use implicit tuple syntax.

    private async Task<(bool IsSuccess, IActionResult Result)> TryLogin(OpenIdConnectRequest request)
    { 
        return (true, BadRequest(new OpenIdErrorResponse
        {
            Error = OpenIdConnectConstants.Errors.AccessDenied,
            ErrorDescription = "Access token provided is not valid."
        }));
    }

return result utilizes the method signature defined property names. e.g:

var foo = await TryLogin(request);
if (foo.IsSuccess)
     return foo.Result;

 

回答3

You cannot have ref or out parameters in async methods (as was already noted).

This screams for some modelling in the data moving around:

public class Data
{
    public int Op {get; set;}
    public int Result {get; set;}
}

public async void Method1()
{
    Data data = await GetDataTaskAsync();
    // use data.Op and data.Result from here on
}

public async Task<Data> GetDataTaskAsync()
{
    var returnValue = new Data();
    // Fill up returnValue
    return returnValue;
}

You gain the ability to reuse your code more easily, plus it's way more readable than variables or tuples.

 

作者:Chuck Lu    GitHub    
posted @   ChuckLu  阅读(119)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2019-07-04 shell script operate the date
2019-07-04 Running .sh scripts in Git bash
2019-07-04 What is the !! (not not) operator in JavaScript?
2019-07-04 JavaScript-Load-Image
2019-07-04 jquery .each
2019-07-04 JavaScript json loop item in array
2019-07-04 Make jQuery throw error when it doesn't match an element
点击右上角即可分享
微信分享提示