C# 使用空合并运算符的隐式转换
我发现我的程序有一种奇怪的行为,经过进一步的分析,我发现我的C#知识或其他地方可能有问题。我相信这是我的错,但我在任何地方都找不到答案C# 使用空合并运算符的隐式转换,c#,null,implicit-conversion,C#,Null,Implicit Conversion,我发现我的程序有一种奇怪的行为,经过进一步的分析,我发现我的C#知识或其他地方可能有问题。我相信这是我的错,但我在任何地方都找不到答案 public class B { public static implicit operator B(A values) { return null; } } public class A { } public class Program { static void Main(string[] args)
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。我不明白为什么它是空的
我在谷歌上搜索了一下,找到了这个问题的答案——有官方的说明
但是按照这个规范,我找不到“b”为空的原因:(也许我读错了,在这种情况下,我为垃圾邮件道歉
如果存在且不是可空类型或引用类型,则会发生编译时错误
……事实并非如此
如果b是动态表达式,则结果类型为动态。在运行时,首先计算a。如果a不为null,则将a转换为动态,并将其作为结果。否则,将计算b,并将其作为结果
……事实并非如此
否则,如果A存在并且是可为null的类型,并且存在从b到A0的隐式转换,则结果类型为A0。在运行时,首先计算A。如果A不为null,则将A展开为类型A0,这将成为结果。否则,计算b并将其转换为类型A0,这将成为结果
…A存在,从b到A0的隐式转换不存在
否则,如果存在A并且存在从b到A的隐式转换,则结果类型为A。在运行时,首先计算A。如果A不为null,则A成为结果。否则,计算b并将其转换为类型A,这将成为结果
…A存在,从b到A的隐式转换不存在
否则,如果b具有类型b且存在从a到b的隐式转换,则结果类型为b。在运行时,首先计算a。如果a不为null,则将a展开为类型A0(如果a存在且可为null),并将其转换为类型b,然后将其变为结果。否则,将计算b并将其变为结果
…b具有类型b,并且存在从a到b的隐式转换。
a被计算为null。因此,b应该被计算,b应该是结果
否则,a和b不兼容,并且会发生编译时错误。
不会发生
我遗漏了什么吗?为什么希望null合并操作符返回
new B()
?a
不是null,因此a??new B()
计算结果为a
现在我们知道将返回a
,我们需要确定结果的类型(T
),以及是否需要将a
强制转换为T
•否则,如果b具有类型b且存在来自的隐式转换
从a到B,结果类型为B。在运行时,首先计算a。如果
不为null,a被展开为A0类型(如果a存在且可为null)
和转换为类型B,这将成为结果。否则,B为
评估并成为结果
存在从A
到B
的隐式转换,因此B
是表达式的结果类型。这意味着A
将隐式转换为B
。隐式运算符返回null
事实上,如果您编写
var b=a??new b();
(注意var
),您将看到编译器推断b
为表达式返回的类型。我们需要查看的部分是空合并表达式的编译时类型
否则,如果b具有类型b且存在从a到b的隐式转换,则结果类型为b。在运行时,首先计算a。如果a不为null,则将a展开为类型A0(如果a存在且可为null),并将其转换为类型b,然后将其变为结果。否则,将计算b并将其变为结果
要将其转换为伪代码:
public Tuple<Type, object> NullCoalesce<TA, TB>(TA a, TB b)
{
...
else if (a is TB) // pseudocode alert, this won't work in actual C#
{
Type type = typeof(TB);
object result;
if (a != null)
{
result = (TB)a; // in your example, this resolves to null
}
else
{
result = b;
}
return new Tuple<Type, object>(type, result);
}
...
}
公共元组NullCoalesce(TA a,TB b)
{
...
否则,如果(a是TB)//伪代码警报,这在实际的C中不起作用#
{
类型=类型(TB);
客观结果;
如果(a!=null)
{
result=(TB)a;//在您的示例中,它解析为null
}
其他的
{
结果=b;
}
返回新元组(类型、结果);
}
...
}
否则,如果b具有类型b并且存在来自a的隐式转换
对于B,结果类型为B。在运行时,首先计算a。如果
如果不为null,则a将展开为A0类型(如果a存在且可为null),并且
转换为类型B,这将成为结果。否则,B为
评估并成为结果
…b具有类型b,并且存在从a到b的隐式转换。a为
计算结果为null。因此,应计算b,且b应为空
结果呢
您的解释是错误的。没有任何说明在执行null
检查之前执行a
到B
的转换。它说明null
检查在转换之前完成
您的案例与此相符:
如果a不为空,则a将被展开为A0类型(如果a存在且为空)
可为空)和转换为类型B,此成为
结果
嗯,说明书上说(为了减少混淆,我改为
x
和y
):
•否则,如果y具有类型y且存在从x到y的隐式转换,则结果类型为y。在运行时,首先计算x。如果x不为null,则将x展开为类型X0(如果x存在且可为null),并将其转换为类型y,然后将其变为结果。否则,计算y并将其变为结果
这种情况会发生。首先,检查左侧的x
,它只是a
,是否为null
。但它本身不是null
。然后
A a = new A();
B b = (B)a ?? new B();