首页 > 解决方案 > 本地函数受益于异步方法

问题描述

根据微软文档

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

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.";
    }
}

我真的不明白这个例子。如果我们只是摆脱本地函数并将其内容提取到外部范围并在验证后立即放置,我们会不会得到相同的结果?在这种情况下,本地函数实际上给出了什么?

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

标签: c#.netasync-awaitc#-7.0

解决方案


两者之间有区别:

  1. 调用PerformLongRunningWork它会引发异常。
  2. 调用PerformLongRunningWork它并成功执行,并返回一个Task<string>包含异常的内容。

那是:

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
}

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

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

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

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


推荐阅读