本地函数受益于异步方法

Ori*_*aev 1 .net c# async-await c#-7.0

根据微软文档

本地函数有两种常见的用例:公共迭代器方法和公共异步方法。这两种类型的方法生成的代码报告错误的时间比程序员预期的要晚。...该技术可以与异步方法一起使用,以确保在异步工作开始之前抛出参数验证引起的异常

public Task<string> PerformLongRunningWork(string address, int index, string name)
{
    if (string.IsNullOrWhiteSpace(address))
        throw new ArgumentException(message: "An address is required", paramName: nameof(address));
    if (index < 0)
        throw new ArgumentOutOfRangeException(paramName: nameof(index), message: "The index must be non-negative");
    if (string.IsNullOrWhiteSpace(name))
        throw new ArgumentException(message: "You must supply a name", paramName: nameof(name));

    return longRunningWorkImplementation();

    async Task<string> longRunningWorkImplementation()
    {
        var interimResult = await FirstWork(address);
        var secondResult = await SecondStep(index, name);
        return $"The results are {interimResult} and {secondResult}. Enjoy.";
    }
}
Run Code Online (Sandbox Code Playgroud)

我真的不明白这个例子。如果我们直接去掉局部函数,把它的内容提取到外部作用域,验证后直接放,是不是也能达到同样的效果?在这种情况下,局部函数实际上给出了什么?

如果它实际上没有改善任何东西,你能想出一个更好的例子吗?

can*_*on7 5

有以下区别:

  1. 调用PerformLongRunningWork它会抛出异常。
  2. 调用PerformLongRunningWork并成功执行,并返回Task<string>包含异常的 a 。

那是:

Task<string> task;
try
{
    task = PerformLongRunningOperation();
}
catch (Exception e)
{
    // PerformLongRunningOperation itself threw
}

bool containsException = task.IsFaulted;

try
{
    string result = await task;
}
catch (Exception e)
{
    // The Task<string> returned from PerformLongRunningWork contained an exception
}
Run Code Online (Sandbox Code Playgroud)

如果从async Task方法中抛出异常,则该异常将包含在Task返回的 中。

因此,具有async委托给async本地函数的非方法的示例将ArgumentException在调用时直接抛出这些方法,而不是将它们包含在Task<string>它返回的内容中。

如果您重写示例以删除本地函数并改为 make PerformLongRunningWork async,那么这些ArgumentExceptions将包含在Task<string>返回的函数中。

你想做哪一个是一个有争议的问题。