【问题标题】:.net compiler error “Not all code paths return a value” on Task method.net 编译器错误“并非所有代码路径都返回值”任务方法
【发布时间】:2020-05-22 10:27:52
【问题描述】:

我已经在实践中了解了 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)
         {
         }
    }

这才是真正让我困惑的地方。如果编译器抛出错误 CS0161 是因为没有返回语句(或其他类似 Task.Run()),那么为什么使用 while(true) 可以修复它?这是否意味着后台的 while(true) 循环运行一个任务?我不这么认为......也许我在这里遗漏了一点。

【问题讨论】:

  • 注意:如果这是您的意图,这不是您通常会编写和启动后台工作程序的方式。

标签: .net asynchronous while-loop compiler-errors task


【解决方案1】:

CS0161 的真正含义并不是真正的“是否每个可能的代码路径都返回一个值”,而是:“是否有一个代码路径以某种方式到达了方法的末尾而没有返回一个值”。编译器巧妙地检测到没有breakwhile (true) 是一个循环,在while 之后无法退出以继续,因此:没有办法到达方法。所以:从编译器的角度来看,它没有做错任何事情

当然,这仍然是非常错误的。

注意:如果添加:

static bool AlwaysTrue() => true;

并更改为while (AlwaysTrue()),它现在会给你一个CS0161错误,因为这个未退出循环的检测特定于常量表达式,它可以简单地评估为true

这与在后台运行 Task 无关。如果你有一个 intstring 作为返回类型,它会做同样的事情。


同样,如果你这样做,它会给你一个 CS0162 警告(检测到无法访问的代码):

while (false)
{
    Console.WriteLine("Hi");
}

【讨论】:

  • 感谢 Marc 的解释。我仍然难以理解的唯一一件事是为什么以下代码可以编译: private Task StartDataCollection() { while(true) { } } 但不是没有 while(true) 循环。
  • @RaminToussi 再次显示:向我展示一个语义上有效的代码路径,它到达方法的末尾而不返回值 - 没有一个,因为编译器知道没有breakwhile(true) 循环永远不会退出 while
猜你喜欢
  • 2012-04-24
  • 2014-02-07
  • 2013-09-07
  • 1970-01-01
  • 2013-07-01
  • 2014-04-16
  • 2015-02-07
相关资源
最近更新 更多