I have learned in practice how Task works in .net but I am still little bit confused with some aspects in the meaning of it. While refactoring an old code I just happened to have the following unfinished piece of code in one of my classes:
private Task StartDataCollection()
{
// Some other code here but no Task.Run()
}
And ofcourse the compiler complains:
Error CS0161 ... : not all code paths return a value
Then I added a while loop to the code as below and the compiler error is gone:
private Task StartDataCollection()
{
while(true)
{
}
}
Just for curiosity I changed the while loop like below and compiler complains for the same error again:
private Task StartDataCollection()
{
while(false)
{
}
}
And this is what really confuses me. If the compiler throws the Error CS0161 because there is no return statement (or something else as Task.Run()) then why a while(true) can fix it? Does it mean that a while(true) loop in the background runs a Task? I don't think so....Maybe I am missing a point here.
The real meaning of CS0161 isn't really "does every possible code path return a value", but rather: "is there a code path that somehow reaches the end of the method and does not return a value". The compiler is cleverly detecting that while (true)
without a break
is a loop that can't be exited to continue after the while
, so: there is no way of reaching the end of the method. So: it isn't doing anything wrong from the compiler's perspective.
It is still very wrong, of course.
Note: if you add:
static bool AlwaysTrue() => true;
and change to while (AlwaysTrue())
, it will now give you a CS0161 error, because this detection of a non-exited loop is specific to constant expressions that it can trivially evaluate as true
.
It has nothing to do with running a Task
in the background. It would do the same if you had an int
or string
as a return type.
Similarly, it will give you a CS0162 warning (unreachable code detected) if you do:
while (false)
{
Console.WriteLine("Hi");
}
Thanks Marc for your explanation. The only thing I still have hard time to understand is why the following code compiles: private Task StartDataCollection() { while(true) { } } but not without the while(true) loop.
@RaminToussi again: show me a semantically valid code path where it reaches the end of the method without returning a value - there isn't one, because the compiler knows that a
while(true)
loop without abreak
never exits to go beyond thewhile