C# Compiler bug: allows for conversion from Nullable<decimal> to decimal

Viewed 93

Consider following code:

    public class DecimalWrapper
    {
        public static implicit operator DecimalWrapper(decimal x) => new();
    }

    [Fact]
    public void Test()
    {
        // Why this even compiles? Since there is no implicit conversion from decimal? -> decimal
        DecimalWrapper c = (decimal?)null; // variable 'c' is null!
    }

I would not expect it to compile at all, since there is no implicit conversion from decimal? to decimal.

I consider it a bug or do I get something wrong?

I have seen this: Serious bugs with lifted/nullable conversions from int, allowing conversion from decimal

but this looks different and it is old (7+ years), so the bugs should be fixed by now, but cannot be sure since all the links to bug reports are gone)... :(

I would really like to use such code in real solution (tracking of calculations), but this prevents me from it.

PS: I am compiling on Windows.

1 Answers

According to specification lifted conversion operators are allowed only for value type to value type conversions (and their nullable counterparts) but in the Roslyn compiler source code you can find next comment:

DELIBERATE SPEC VIOLATION:
The native compiler allows for a "lifted" conversion even when the return type of the conversion not a non-nullable value type. For example, if we have a conversion from struct S to string, then a "lifted" conversion from S? to string is considered by the native compiler to exist, with the semantics of "s.HasValue ? (string)s.Value : (string)null". The Roslyn compiler perpetuates this error for the sake of backwards compatibility.

So it seems to be an actuall bug which was introduced for backwards compatibility. And the decompilation shows exactly that behaviour.

Related