16

带有 XML 文档的示例方法:

// summary and param tags are here when you're not looking.
/// <exception cref="ArgumentNullException>
///    <paramref name="text" /> is null.
/// </exception>
public void Write(string text)
{
    if (text == null)
        throw new ArgumentNullException("text", "Text must not be null.");

    // sync stuff...
}

Write(null)按预期抛出异常。这是一个异步方法:

public async Task WriteAsync(string text)
{
    if (text == null)
        throw new ArgumentNullException("text", "Text must not be null.");

    // async stuff...
}

WriteAsync(null), 在等待之前不会抛出异常。我应该ArgumentNullExceptionexception标签中指定吗?我认为这会让消费者认为调用WriteAsync可能会抛出一个ArgumentNullException并写下这样的东西:

Task t;
try
{
    t = foo.WriteAsync(text);
}
catch (ArgumentNullException)
{
    // handling stuff.
}

在异步方法中记录异常的最佳实践是什么?

4

3 回答 3

10

不是直接的答案,但我个人建议在这里倾向于快速失败;这可能意味着编写 2 种方法:

public Task WriteAsync(string text) // no "async"
{
    // validation
    if (text == null)
        throw new ArgumentNullException("text", "Text must not be null.");

    return WriteAsyncImpl(text);
}
private async Task WriteAsyncImpl(string text)
{
    // async stuff...
}

这种模式也是添加“快速路径”代码的理想场所,例如:

public Task WriteAsync(string text) // no "async"
{
    // validation
    if (text == null)
        throw new ArgumentNullException("text", "Text must not be null.");

    if (some condition)
        return Task.FromResult(0); // or similar; also returning a pre-existing
                                   // Task instance can be useful

    return WriteAsyncImpl(text);
}
于 2013-04-09T13:07:23.233 回答
3

微软似乎没有区分async抛出异常的方法和返回Task的异常存储在其Exception属性中的方法。例如:

WebClient.DownloadFileTaskAsync(string, string)

就个人而言,我会选择将异常记录为返回值(即返回的Task)文档的一部分,因为这种区别可能对客户很重要。

于 2013-04-09T22:05:29.817 回答
0

我建议保留异常标签,因为它们出现在 Intellisense 中。

力求简洁,我不会提及异常是否快速失败,只要这遵循直觉。也就是说,健全性检查应该快速失败,而执行期间的失败则不应该。如果您必须偏离此规则,请记录下来。

请注意,更改异常是同步抛出(快速失败)还是等待时可能会破坏客户代码。

于 2019-11-15T09:43:30.957 回答