CS1998 "method lacks await operators" 的原因是什么?

12
当一个async方法没有任何await操作符时,C#编译器会产生CS1998警告。
这个警告的背后原因是什么?
我知道使用async会增加状态机和异常处理,从而增加了方法的开销。
这个警告的主要原因是性能吗? 还是它的作用是提醒我可能忘记了在某个地方使用await?
也许语言设计团队的成员可以为我们解答一下这个问题... :)
(请不要回答“你可以去掉async以消除警告”,我想知道警告背后的原因和决策,而不是绕过警告的方法。)

7
如果一个方法中没有任何await,那么它被定义为async似乎没有什么意义。 - juharr
6
我不是语言设计师,但新程序员常犯的一个明显错误假设是,标记为“async”的方法会以某种方式异步执行。如果没有任何await操作符,这显然是不正确的。对于这种情况,“这不会达到你的预期,并且有更好的编写方式来实现你想要的效果”是编译器警告的明显候选情况。 - Jeroen Mostert
@juharr,当被调用者是“async”时,它会改变调用者的异常行为。 - cpt. jazz
1
@juharr,原因之一是:Task<TResult>没有协变性,因此如果您使用Task.FromResult()返回某些内容,则可能需要手动指定泛型类型,而不是让类型推断(如果您的方法返回值的超类与您传递给Task.FromResult()的值相同)。如果您必须实现诸如Task MyMethod()这样的方法签名,则编写async Task MyMethod() { DoSomething(); }比编写Task MyMethod() { DoSomething(); return Task.CompletedTask; }更加简洁。 - binki
1
@JeroenMostert 这不仅仅是“新手程序员”不理解这些东西的问题吗?为什么“另一种做法”更好呢? - Victor Yarema
1个回答

12
警告的原因是什么?
简单来说,一个不使用await的async方法几乎肯定是错误的。并非总是错误,否则它将是一个错误。但几乎总是错误,这就是警告的原因。
新手常见的async错误是认为“async”意味着“使此方法异步化”,通常伴随着“异步”意味着“在后台线程上运行”的假设,但有时只是一种“魔法”的假设。
因此,警告明确指出代码将会同步运行。
我也发现当重构我的代码时,这个警告很有用。有时我会得到一个应该改为同步的async方法,而这个警告指出了这一点。
没有使用await的async可能有用,以减少代码量,如果你有非平凡的(即可能产生异常)同步代码,并且需要实现一个异步方法签名。在这种情况下,您可以使用async来避免半打TaskCompletionSource和try / catch代码。但这只是一个极小的用例;大多数时候,警告是有帮助的。

你提到的异常处理情况正是我目前面临的场景。我曾考虑忽略这个警告,但不确定这是否是一个好主意。通过你的回答,我觉得在某些情况下抑制警告是可以的。感谢你的帮助! - cpt. jazz
4
我认为避免return Task.CompletedTask;或需要手动指定TResult的情况是“极小的使用案例”,因为当使用Task<SuperClass> MyMethodAsync() => Task.FromResult(subClassValue);(编译错误,无法将Task<SubClass>强制转换为Task<SuperClass>)时,类型推断会选择方法返回类型的子类。这种情况下禁用此警告比任何好处都更重要。我个人通过<PropertyGroup><NoWarn>CS1998</NoWarn></PropertyGroup>来禁用此警告... - binki
1
我遇到了一个棘手的错误,在应该返回Task的地方返回了null。在异步方法中没有问题,但在其他情况下非常糟糕。我拥有所有带有虚拟方法的异步签名,但并非基类中的所有方法都需要它。为了避免警告,我生活在那种混合状态中。直到现在。我将放弃那个警告。我现在知道自己在做什么。 - ygoe
6
编译器为什么要试图向“async-新手”“解释”一些东西?我认为它应该只是检查代码并编译。就这样。 还有一句话“简单来说,一个不使用await的异步方法几乎肯定是错误的”,没有解释,只是一种声明,甚至没有示例。那些“错误”的情况是什么? 我仍然不明白这个警告有什么用处。 - Victor Yarema
1
@VictorYarema:最好的错误信息是可操作的。因此,近年来编译器试图改进其错误信息,而不是让开发人员去谷歌它们。这并不总是这样;在90年代末,我实际上建立了一个包含C++错误及其含义的文档。关于没有awaitasync,通常之所以出错的原因是async关键字的主要目的启用await关键字:https://blogs.msdn.microsoft.com/ericlippert/2010/11/11/asynchrony-in-c-5-part-six-whither-async/ - Stephen Cleary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接