C# 未实现/支持/操作无效异步方法
将异步方法标记为未实现/不支持或无效操作的正确方法是什么。为了简单起见,我将在示例中仅使用C# 未实现/支持/操作无效异步方法,c#,async-await,C#,Async Await,将异步方法标记为未实现/不支持或无效操作的正确方法是什么。为了简单起见,我将在示例中仅使用NotImplementedException,但问题同样适用于NotSupportedException和invalidoOperationException 通过同步方式,可以简单地引发异常: public override void X() { throw new NotImplementedException(); } 在异步世界中,这段代码的等价物是什么 /* 1 */ public o
NotImplementedException
,但问题同样适用于NotSupportedException
和invalidoOperationException
通过同步方式,可以简单地引发异常:
public override void X() {
throw new NotImplementedException();
}
在异步世界中,这段代码的等价物是什么
/* 1 */ public override Task XAsync() {
throw new NotImplementedException();
}
或
/* 2 */ public override Task XAsync() {
return Task.FromException(new NotImplementedException());
}
这些方法的复杂性是什么?有没有更好的方法
为了避免“不,这里不需要异步的方法”/“它不是异步的”,我想说该方法实现了一些接口或抽象类
我没有考虑的一些方法:
/* 3 */ public async override Task XAsync() { // here is an CS1998 warning
throw new NotImplementedException();
}
编译器,在语义上等同于2
/* 4 */ public async override Task XAsync() {
await Task.Yield();
throw new NotImplementedException();
}
这与3相同,但添加了wait on Task.Yeild() 当调用返回
任务的方法时,它的某些部分是同步执行的(即使实现方法定义为异步
,并且其中包含等待
调用..在第一次调用之前,默认情况下一切都是同步的)
因此,所有选项的结果都是一样的:立即抛出或返回一个已完成但有异常的任务(只有在您立即等待调用时才会有相同的行为)或标记一个方法async
(这将要求您有await
调用,但为了完整性,让我们添加它)
我会立即抛出,因为返回任务可能表示您“已开始工作”,并且调用方不需要等待任务,因此如果调用方并不真正关心您的任务
何时完成(它甚至没有返回值),没有实现该方法的事实不会显示出来。我要冒险说“没关系。”
可以直接抛出(throw
)或放置在返回的任务上(task.FromException
)。因为它们是骨头异常,所以无论如何都不应该被捕获,所以不管它们被抛出到哪里。在您的评论中,您写道:
我们正在尝试制作NHibernate的异步版本:)
这让您陷入了一个不幸的境地:由熟练程序员编写的著名库应该编写得很好,以防止技能较低的程序员意外误用(包括通过复制/粘贴误用)
有足够多的人期望像这样的代码等待任务。当所有(a(),b(),c())
即使其中一个异步操作失败也能工作时,我认为您的第一个选项甚至不应该是选项。如果b()
同步抛出异常,那么a()
返回的任务将被忽略,而c()
不会被调用
我同意Stephen Cleary的回答,他说,NotImplementedException
是一个愚蠢的例外,不重要,因为它无论如何都不应该出现在生产代码中。然而,你写道:
该问题也适用于不支持异常
和无效操作异常
这些不一定是愚蠢的例外。这些可能最终会出现在生产代码中
你的第二个选择避免了这个问题
您的第二个选项确实有一个额外的问题:它不会引发异常。因为实际上没有抛出异常,所以您妨碍了调试:当出现问题时,在调试器中提供在抛出异常的位置而不是捕获异常的位置中断的选项是非常有用的
我建议也考虑一下
public async override Task XAsync() {
throw new NotImplementedException();
}
由于与创建状态机相关的开销,您放弃了它。我认为这不是放弃它的正当理由。这是与性能无关的代码,这是只处理错误情况的代码。我建议这样做是因为一般来说,我赞成使用async
/wait
而不是直接操作任务,因为这样更容易发现愚蠢的错误,因为在开发时间中节省的时间足够值得
我理解你为什么不想接受这个选择,但我个人还是会的。它避免了第一种选择的缺点。它避免了第二种选择的缺点。根据我的经验,它自身的缺点是性能稍慢,与其他两个相比,它不太可能成为问题
在其他两个问题中,希望缺点的细节能帮助您做出明智的决定。好问题。第一个选项在调用方法时抛出异常,第二个选项在等待结果时抛出异常。我对第一种选择有一点偏好,因为它“很早就失败了”,但我很好奇专家们会怎么说。也许它会有帮助:是的,@FelipeOriani看到了,谢谢“除非你澄清你试图涵盖的具体场景”我们正试图制作一个异步版本的NHibernate:)@hazzik是的。你不明白我的评论吗?我是说异步任务XAsync(){throw…;}
是另一种选择。使用async
关键字。虽然我倾向于这样。。。它不会构建bc,没有等待。如果您只抛出一个返回任务的方法,那么不要使用async
关键字定义您的方法。