未实现/支持/无效操作异步方法

haz*_*zik 14 c# async-await

将async方法标记为未实现/不支持或无效操作的正确方法是什么.为了简单,我会用唯一NotImplementedException的例子,但问题适用于NotSupportedExceptionInvalidOperationException为好.

以同步方式,可以简单地抛出异常:

public override void X() {
    throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)

异步世界中这段代码的等价物是什么?

/* 1 */ public override Task XAsync() {
    throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)

要么

/* 2 */ public override Task XAsync() {
    return Task.FromException(new NotImplementedException());
}
Run Code Online (Sandbox Code Playgroud)

这些方法的并发症有哪些?有没有更好的方法?


为了避免"Nah,你不需要一个方法在这里异步"/"它不是异步"我会说该方法实现了一些接口或抽象类.


我不考虑的一些方法:

/* 3 */ public async override Task XAsync() { // here is an CS1998 warning 
    throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)

编译器只会生成无用的状态机,它在语义上等效于2

/* 4 */ public async override Task XAsync() {
    await Task.Yield();
    throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)

3 相同,但在Task.Yeild()上添加等待;

Mar*_*ich 5

当调用返回 a 的方法时Task,它的某些部分是同步执行的(即使实现方法被定义为async并且其中有await调用......直到第一次离开,默认情况下一切都是同步的)。

因此,所有选项的结果都是相同的:立即抛出或返回一个已完成但有异常的任务(仅当您立即等待调用时行为相同)或标记一个方法async(这会期望您有await调用,但让我们添加为了完整性)。

我会立即抛出,因为返回任务可能表明您“已经开始工作”,并且调用者不需要等待任务,因此如果调用者并不真正关心您何时Task完成(它甚至不关心)有返回值),该方法未实现的事实不会显示出来。


Ste*_*ary 5

我要弯腰说“没关系”。

骨头异常可以直接引发(throw),也可以放在返回的任务(Task.FromException)上。由于它们是异常的异常,因此无论如何都不应将它们捕获,因此将它们扔到哪里都没有关系。