我已经在实践中学习了Task在.net中的工作方式,但是我对它的含义有些困惑。重构旧代码时,我碰巧在我的一个类中有以下未完成的代码:
private Task StartDataCollection()
{
// Some other code here but no Task.Run()
}
当然,编译器会抱怨:
错误CS0161 ...:并非所有代码路径都返回一个值
然后我在代码中添加了一个while循环,如下所示,编译器错误消失了:
private Task StartDataCollection()
{
while(true)
{
}
}
出于好奇,我更改了while循环,如下所示,编译器再次抱怨相同的错误:
private Task StartDataCollection()
{
while(false)
{
}
}
这真是让我感到困惑。如果编译器因为没有return语句(或诸如Task.Run()之类的其他东西)而抛出Error CS0161,那么为什么while(true)可以解决它?这是否意味着在后台运行while(true)循环运行Task?我不这样认为。。。也许我在这里遗漏了一点。
CS0161的真正含义不是真正地“是否所有可能的代码路径都返回一个值”,而是:“是否存在某种方式到达方法末尾且不返回值的代码路径”。编译器正在巧妙地检测到,while (true)
如果没有a,break
则循环是无法退出的,因此在之后必须继续执行while
:因此,无法到达方法的结尾。所以:从编译器的角度来看,它没有做错任何事情。
当然,这仍然是非常错误的。
注意:如果添加:
static bool AlwaysTrue() => true;
并更改为while (AlwaysTrue())
,它现在会给您一个CS0161错误,因为这种对未退出循环的检测是特定于常量表达式的,可以简单地将其求值为true
。
它与Task
在后台运行a无关。如果您具有int
或string
作为返回类型,它将执行相同的操作。
同样,如果执行以下操作,则会发出CS0162警告(检测到无法访问的代码):
while (false)
{
Console.WriteLine("Hi");
}
感谢Marc的解释。我仍然很难理解的唯一原因是为什么要编译以下代码:私有任务StartDataCollection(){while(true){}}但并非没有while(true)循环。
@RaminToussi再次:向我展示一个语义上有效的代码路径,该路径在不返回值的情况下到达方法的末尾- 没有一个,因为编译器知道
while(true)
没有break
永不退出的循环超出了while