无法将异步lambda表达式转换为委托类型'Func'

本文关键字:bool string Func 类型 异步 lambda 表达式 转换 | 更新日期: 2023-09-27 18:15:16

我得到一个错误与以下代码。

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>'.
 }

这个方法调用以下函数

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

它看起来很像:将异步lambda表达式转换为委托类型System.Func?但是,这个解决方案对我不起作用

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;

然后resharper给了我提供的代码,但是仅仅添加async关键字是不行的。

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

将给我错误:async方法的返回类型必须是void, task或task。

任何想法?

无法将异步lambda表达式转换为委托类型'Func<bool, string, bool>'

我个人将使用foreach实现,但回答具体问题。

如果没有async,使用的Aggregate过载具有以下特征:

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

注意func参数-它是一个接收boolstring返回bool的方法。重要的是,第一个实参的类型与结果的类型以及seed形参的类型相同。

因为async lambda必须返回Task的派生对象。您需要bool的结果,所以让我们将其替换为Task<bool>:

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

,导致以下解决方案:

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));

使用ContinueWith和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;
            };