C# 编译器错误:允许从 Nullable<decimal> 转换为十进制
C# Compiler bug: allows for conversion from Nullable<decimal> to decimal
考虑以下代码:
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!
}
我根本不希望它编译,因为没有十进制的隐式转换?到十进制。
我认为这是一个错误还是我弄错了什么?
我看过这个:
Serious bugs with lifted/nullable conversions from int, allowing conversion from decimal
但这看起来不一样,而且已经过时(7 年以上),所以这些错误现在应该已修复,但不能确定,因为所有指向错误报告的链接都消失了)...:(
我真的很想在实际解决方案(计算跟踪)中使用这样的代码,但这阻止了我。
PS:我正在 Windows.
上编译
根据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你可以找到下一条评论:
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.
所以这似乎是为了向后兼容而引入的实际错误。而 decompilation 恰好显示了这种行为。
考虑以下代码:
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!
}
我根本不希望它编译,因为没有十进制的隐式转换?到十进制。
我认为这是一个错误还是我弄错了什么?
我看过这个: Serious bugs with lifted/nullable conversions from int, allowing conversion from decimal
但这看起来不一样,而且已经过时(7 年以上),所以这些错误现在应该已修复,但不能确定,因为所有指向错误报告的链接都消失了)...:(
我真的很想在实际解决方案(计算跟踪)中使用这样的代码,但这阻止了我。
PS:我正在 Windows.
上编译根据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你可以找到下一条评论:
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 fromstruct S
tostring
, then a "lifted" conversion fromS?
tostring
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.
所以这似乎是为了向后兼容而引入的实际错误。而 decompilation 恰好显示了这种行为。