Note: this appears to have been fixed in Roslyn
This question arose when writing my answer to this one, which talks about the associativity of the n
If you take a look at the generated code for the Left-grouped case it actually does something like this (csc /optimize-):
C? first;
A? atemp = a;
B? btemp = (atemp.HasValue ? new B?(a.Value) : b);
if (btemp.HasValue)
{
first = new C?((atemp.HasValue ? new B?(a.Value) : b).Value);
}
Another find, if you use first it will generate a shortcut if both a and b are null and return c. Yet if a or b is non-null it re-evaluates a as part of the implicit conversion to B before returning which of a or b is non-null.
From the C# 4.0 Specification, §6.1.4:
- If the nullable conversion is from
S?toT?:
- If the source value is
null(HasValueproperty isfalse), the result is thenullvalue of typeT?.- Otherwise, the conversion is evaluated as an unwrapping from
S?toS, followed by the underlying conversion fromStoT, followed by a wrapping (§4.1.10) fromTtoT?.
This appears to explain the second unwrapping-wrapping combination.
The C# 2008 and 2010 compiler produce very similar code, however this looks like a regression from the C# 2005 compiler (8.00.50727.4927) which generates the following code for the above:
A? a = x;
B? b = a.HasValue ? new B?(a.GetValueOrDefault()) : y;
C? first = b.HasValue ? new C?(b.GetValueOrDefault()) : z;
I wonder if this is not due to the additional magic given to the type inference system?