用null进行隐式转换

我发现了程序中一个奇怪的行为,经过进一步分析后,我发现在我的C#知识或其他地方可能有问题。 我相信这是我的错误,但我无法在任何地方找到答案...

public class B
{
    public static implicit operator B(A values) 
    {
        return null; 
    }
}
public class A { }

public class Program
{
    static void Main(string[] args)
    {
        A a = new A();
        B b = a ?? new B();
        //b = null ... is it wrong that I expect b to be B() ?
    }
}

此代码中的变量“b”被评估为null。 我不明白为什么它是空的。

我搜索了一下,在这个问题中发现了一个回应 - 隐式转换Null-Coalescing运算符的结果 - 与官方规范。

但遵循这个规范,我找不到“b”为null的原因:(也许我读错了,在这种情况下,我为发送垃圾邮件道歉。

如果A存在并且不是可为空的类型或引用类型,则会发生编译时错误。

......情况并非如此。

如果b是动态表达式,则结果类型是动态的。 在运行时,首先评估a。 如果a不为空,则a被转换为动态,并且这成为结果。 否则,b被评估,并且这成为结果。

...情况并非如此。

否则,如果A存在并且是可为空的类型,并且存在从b到A0的隐式转换,则结果类型为A0。 在运行时,首先评估a。 如果a不为空,则将a解包为A0类型,并将其作为结果。 否则,评估b并将其转换为A0类型,并将其作为结果。

...存在,从b到A0的隐式转换不存在。

否则,如果A存在并且存在从b到A的隐式转换,则结果类型为A.在运行时,首先评估a。 如果a不为空,则a成为结果。 否则,评估b并将其转换为A类型,并将其作为结果。

...存在,从b到A的隐式转换不存在。

否则,如果b具有类型B并且存在从a到B的隐式转换,则结果类型为B.在运行时,首先评估a。 如果a不为空,则将a解包为A0类型(如果A存在并且可为空)并将其转换为B类型,则这将成为结果。 否则,b被评估并成为结果。

... b具有类型B并且存在从a到b的隐式转换.a被评估为空。 因此,b应该被评估,b应该是结果。

否则,a和b不兼容,并发生编译时错误。 没有发生

我错过了什么吗?


那么,规范说(我更改为xy以减少混淆):

•否则,如果y的类型为Y,并且存在从x到Y的隐式转换,则结果类型为Y.在运行时,首先计算x。 如果x不为空,则将x解包为X0类型(如果X存在并且可为空)并将其转换为Y类型,则这将成为结果。 否则,y被评估并成为结果。

有时候是这样的。 首先,检查左侧的x (仅为a )为null 。 但它本身并非null 。 然后,左手侧被使用。 然后运行隐式转换。 其类型B结果是... null

请注意,这不同于:

    A a = new A();
    B b = (B)a ?? new B();

在这种情况下,左操作数是一个表达式( x ),它本身为null ,结果变成右边( y )。

也许在引用类型之间的隐式转换应该返回null (如果和),只有当原始值为null ,这是一种很好的做法?


我猜想编写这个规范的人可以像这样做(但没有):

•否则,如果y的类型为Y,并且存在从x到Y的隐式转换,则结果类型为Y.在运行时,首先计算x并将其转换为Y类型。如果该转换的输出不为null,该输出成为结果。 否则,y被评估并成为结果。

也许这会更直观? 无论转换的输入是否为null它都会强制运行时调用隐式转换。 如果典型实现迅速确定null → null ,那么这应该不会太昂贵。


你为什么期望null-coalescing运算符返回new B()a不是null,所以a ?? new B() a ?? new B()评估为a

现在我们知道a会被返回,我们需要确定结果的类型( T )以及是否需要将aT

•否则, 如果b具有类型B并且存在从a到B的隐式转换,则结果类型为B.在运行时,首先评估a。 如果不为空, 一个解包类型A0(如果A存在,并且可为空),并转换为类型B,并且这成为结果 。 否则,b被评估并成为结果。

存在从AB的隐式转换,因此B是表达式的结果类型。 这意味着a将被隐含地转给B 而你的隐式运算符返回null

事实上,如果你写var b = a ?? new B(); var b = a ?? new B(); (注意var ),你会发现编译器推断B是表达式返回的类型。


否则,如果b具有类型B并且存在从a到B的隐式转换,则结果类型为B.在运行时,首先评估a。 如果a不为空,则将a解包为A0类型(如果A存在并且可为空)并将其转换为B类型,则这将成为结果。 否则,b被评估并成为结果。

... b具有类型B并且存在从a到b的隐式转换.a被评估为空。 因此,b应该被评估,b应该是结果。

你正在解释这一个错误。 没有说是aB转换前完成null ,执行检测。 它表示在转换之前完成null检查!

你的情况适合于:

如果a不为空 ,则将a解包为A0类型(如果A存在并且可为空)并将其转换为B类型 ,则这将成为结果

链接地址: http://www.djcxy.com/p/57965.html

上一篇: Implicit conversion with null

下一篇: not exact "7.13 The null coalescing operator" in C# 4.0 spec