Supposing I have a string which I want to convert to an integer, I would do
int i;
int.TryParse(someString, out i);
Now I would like to do the same in a Linq query:
int i;
var numbers =
from s in someStrings
where int.TryParse(s, out i)
select i;
But this refuses to compile with the error
CS0165 Use of unassigned local variable 'i'
It compiles and works as intended when I initialize i to an arbitraty value. But why do I have to?
The query expression is translated into:
var numbers = someStrings.Where(s => int.TryParse(s, out i))
.Select(s => i);
Now, we know that the delegate created from the lambda expression for the Where
call will be executed before the delegate created from the lambda expression for the Select
call, but the compiler doesn't. And indeed, you could easily write your own extension method that didn't obey that:
public static IEnumerable<T> Where<T>(
this IEnumerable<T> source,
Func<T, bool> predicate)
{
// I can't be bothered to check the predicate... let's just return everything
return source;
}
At that point, with the normal Select
call, your delegate returning i
would be executed without every assigning a value to it.
Basically, the definite assignment rules are deliberately quite conservative, avoiding making any assumptions about what methods do etc.
See more on this question at Stackoverflow