I have some code similar to the following.
class MyClass<TEnum> where TEnum : struct
{
public IEnumerable<TEnum> Roles { get; protected set; }
public MyClass()
{
IEnumerable<string> roles = ... ;
TEnum value;
Roles = from r in roles
where Enum.TryParse(r, out value)
select value; // <---- ERROR HERE!
}
}
However, on the line indicated above, I get the error:
Use of unassigned local variable 'value'
Seems to me that value
will always be initialized in this case since it is an out
parameter to Enum.TryParse
.
Is this a bug with the C# compiler?
No it is not.
Compiler cannot guarantee that Enum.TryParse(r, out value)
will be executed.
What if roles
is an empty collection?
Even if you initialize your collection in the method CSC does not consider roles
to have values - it is a thing that compiler currently cannot do.
What if lambda with Enum.TryParse(r, out value)
will not be executed - value
won't get its value through the closure?
Compiler cannot give you such guarantees.
Your code is (partially) equivalent to:
class MyClass<TEnum> where TEnum : struct
{
public IEnumerable<TEnum> Roles { get; protected set; }
public MyClass()
{
IEnumerable<string> roles = ... ;
Roles = GetValues(); // <---- ERROR HERE!
}
public static IEnumerable<TEnum> GetValues(IEnumerable<String> roles)
{
TEnum value;
String[] roleArray = roles.ToArray(); // To avoid the foreach loop.
// What if roleArray.Length == 0?
for(int i = 0; i < roleArray.Length; i++)
{
// We will never get here
if (Enum.TryParse(roleArray[i], out value))
yield return value;
}
}
}
And this code is clean and understandable for the compiler(no errors) - it knows that without the execution of the Enum.TryParse(roleArray[i], out value)
you won't try to return value
.
But it is not so simple with functional LINQ query.
If we rewrite it with Enumerable extensions we will have:
TEnum value;
Roles = roles
.Where(role => Enum.TryParse(role, out value))
.Select(role => value); <---- STILL ERROR HERE!
And we again get the error.
Compiler cannot see that value
will be unquestionably set, because it does not understand the innards of the methods used - Where
may or (theoretically)may not execute the lambda, so if you add the fact that value
variable is used in closure, it becomes a non trivial task to make such guarantees without false positives.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With