Curious null-coalescing operator custom implicit conversion behaviour

前端 未结 5 1334
粉色の甜心
粉色の甜心 2020-11-30 16:32

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

5条回答
  •  挽巷
    挽巷 (楼主)
    2020-11-30 16:44

    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? to T?:
      • If the source value is null (HasValue property is false), the result is the null value of type T?.
      • Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping (§4.1.10) from T to T?.

    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?

提交回复
热议问题