简体   繁体   中英

Cannot convert async lambda expression to delegate type 'Func<bool, string, bool>'

I am getting an error with the following code.

public async Task<bool> FlushUrlAsync(Uri url, bool recursive, CancellationToken token = default(CancellationToken))
{
    _serverPortsConfig.CacheServerPorts
        .Select(cacheServerPort => $"http://{url.Host}:{cacheServerPort}{url.AbsolutePath}")
        .Aggregate(true, (current, memoryCacheUrl) => current && await FlushUrlAsync(recursive, memoryCacheUrl)); //<--- produces the next error:
    // Cannot convert async lambda expression to delegate type
    // 'Func<bool, string, bool>'. An async lambda expression may return 
    // void, Task or Task<T>, none of which are convertible to
    // 'Func<bool, string, bool>'.
 }

This method calls the following function

private async Task<bool> FlushUrlAsync(bool recursive, string memoryCacheUrl)
{
    return await someMagic(); //for clearity I removed the code.
}

It looks a lot like: Convert async lambda expression to delegate type System.Func<T>? , howevery, there solution won't /can't get it to work for me.

I had:

var result = true;
foreach (var cacheServerPort in _serverPortsConfig.CacheServerPorts)
{
    var memoryCacheUrl = $"http://{url.Host}:{cacheServerPort}{url.AbsolutePath}";
    result = result && await FlushUrlAsync(memoryCacheUrl, recursive);
}

return result;

Then resharper gave me the code that is provided, but just adding the async keyword doesn't work.

.Aggregate(true, async (current, memoryCacheUrl) => current && await FlushUrlAsync(recursive, memoryCacheUrl));

will give me the erorr: the return type of async method must be void, task or Task.

any ideas?

I would personally use the foreach implementation, but answering the concrete question.

Without async the Aggregate overload used has the following signature:

bool Aggregate<bool, string>(bool seed, Func<bool, string, bool> func)

Note the func parameter - it's a method receiving bool and string returning a bool . The important part is that the type of the first argument is the same as the type of the result, as well as the type of seed parameter.

Since async lambda must return a Task derived object. You need a bool result, so let substitute it with Task<bool> :

Task<bool> Aggregate<bool, string>(Task<bool> seed, Func<Task<bool>, string, Task<bool>> func)

which leads to the following solution:

return await _serverPortsConfig.CacheServerPorts
    .Select(cacheServerPort => $"http://{url.Host}:{cacheServerPort}{url.AbsolutePath}")
    .Aggregate(Task.FromResult(true), async (current, memoryCacheUrl) => 
        await current && await FlushUrlAsync(recursive, memoryCacheUrl));

Use ContinueWith with TaskContinuationOptions,

 Func<Exception, bool> handlerFunc = (Exception ex) =>
            {

                 ex.HandleExceptionAsync().ContinueWith(async (result) => 
                 {
                    // all await operations can be called here
                 }, System.Threading.Tasks.TaskContinuationOptions.OnlyOnRanToCompletion);

                return true;
            };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM