用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不兼容,并发生编译时错误。 没有发生
我错过了什么吗?
那么,规范说(我更改为x
和y
以减少混淆):
•否则,如果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
)以及是否需要将a
为T
•否则, 如果b具有类型B并且存在从a到B的隐式转换,则结果类型为B.在运行时,首先评估a。 如果不为空, 一个解包为类型A0(如果A存在,并且可为空),并转换为类型B,并且这成为结果 。 否则,b被评估并成为结果。
存在从A
到B
的隐式转换,因此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应该是结果。
你正在解释这一个错误。 没有说是a
以B
转换前完成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