async Func

方法内的 3 个调用有什么区别WhatDifferences?


这是测试代码:


async Task WhatDifferences(Context context)

{

    await ActionAsync(context, async x => await IsOddAsync(x).ConfigureAwait(false));

    await ActionAsync(context, x => IsOddAsync(x));

    await ActionAsync(context, IsOddAsync);

}


async Task<T> ActionAsync<T>(Context context, Func<Context, Task<T>> action)

{

    return await action(context).ConfigureAwait(false);

}


async Task<bool> IsOddAsync(Context context)

{

    return await Task.Run(() => context.Count++ % 2 == 1).ConfigureAwait(false);

}


class Context

{

    public int Count { get; set; }

}

我正在尝试决定在我的代码库中使用哪一个,并且根据我的知识,所有 3 个的行为都是相同的。


问题与不同传递异步委托的方法签名是什么?


如果我表现得更有逻辑,你可能会知道我的担忧


async Task<T> ActionAsync<T>(Context context, Func<Context, Task<T>> action)

{

    using (var transaction = new TransactionScope())

    {

        //do some async logic before action

        var result = await action(context).ConfigureAwait(false);

        //do other async validation logic after action

        return result;

    }

}


饮歌长啸
浏览 78回答 2
2回答

慕婉清6462132

我正在尝试决定在我的代码库中使用哪一个,并且根据我的知识,所有 3 个的行为都是相同的。在这个具体例子中,这基本上是正确的。此创建一个引用 IsOddAsync 方法的委托:await ActionAsync(context, IsOddAsync);这个为 lambda 表达式创建一个方法,委托引用编译器生成的方法:await ActionAsync(context, x => IsOddAsync(x));这个函数的作用相同,但对于异步 lambda,因此编译器生成的方法也有一个 async 状态机:await ActionAsync(context, async x => await IsOddAsync(x).ConfigureAwait(false));一般来说,你的问题可以归结为两个问题:我应该使用方法组而不是 lambda 吗?是的你应该。这样做没有任何缺点,而且效率更高、代码更短,而且对可维护性没有任何影响。我应该删除async/await还是保留关键字?这个更加细致。在这种特殊情况下省略 没问题,因为 lambda 所做的只是调用单个方法并传递其参数。在调用 之前或之后,lambda 不可能抛出异常。async asyncIsOddAsync但是,如果您的 lambda 更复杂 - 在将 x 传递给 IsOddAsync 之前对其进行操作,或者对结果进行操作,或者使用using 块,那么您需要保留 async/await 关键字以获得最大的可维护性。

鸿蒙传说

await与返回Task和...之间的不同:await ActionAsync(context, async x => await IsOddAsync(x).ConfigureAwait(false)); await ActionAsync(context, x => IsOddAsync(x));在某些情况下,您不需要 await(当然也不需要 async)执行异步操作的方法不需要使用await,如果:方法内部只有一次异步调用异步调用在方法的最后没有必要捕获/处理任务中可能发生的异常在这种情况下,您可以中间返回Task。请注意,行为上存在细微差别 - 取决于IsOddAsync的实现:重要提示:返回任务而不是等待它,会更改方法的异常行为,因为它不会在启动任务的方法中抛出异常,而是在等待任务的方法中抛出异常。正如 Gabriel Luci 所指出的,在当前实现的 IsOddAsync(一次调用和一次 await)中,行为没有差异。x => IsOddAsync(x)与IsOddAsync和...之间的不同await ActionAsync(context, x => IsOddAsync(x)); await ActionAsync(context, IsOddAsync);在第一个中,您将使用参数创建一个匿名 (lambda) 方法x。由于 IsOddAsync 也有一个参数(类型相同),因此不需要 lambda 方法。请注意,如果 IsOddAsync 有其他参数,例如,您需要 lambda和第二个参数,那么你需要 lambda。示例:await ActionAsync(context, x => IsOddAsync(x, "mySecondParameter"));在这种情况下,除了内部抛出异常时的调用堆栈之外,行为没有任何区别。
打开App,查看更多内容
随时随地看视频慕课网APP