Implicit conversion with null-coalescing operator
我发现我的程序有一种奇怪的行为,经过进一步的分析,我发现我的C知识或其他地方可能有问题。我以为这是我的错,但我在任何地方都找不到答案…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
此代码中的变量"b"的计算结果为空。我不明白为什么它是空的。
我在google上找到了这个问题的响应——隐式的空合并操作符结果的强制转换——符合官方规范。
但是按照这个规范,我找不到"b"为空的原因:(也许我读错了,在这种情况下,我为垃圾邮件道歉。
If A exists and is not a nullable type or a reference type, a compile-time error occurs.
…事实并非如此。
If b is a dynamic expression, the result type is dynamic. At run-time, a is first evaluated. If a is not null, a is converted to dynamic, and this becomes the result. Otherwise, b is evaluated, and this becomes the result.
…也不是这样。
Otherwise, if A exists and is a nullable type and an implicit conversion exists from b to A0, the result type is A0. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0, and this becomes the result. Otherwise, b is evaluated and converted to type A0, and this becomes the result.
…A存在,从B到A0的隐式转换不存在。
Otherwise, if A exists and an implicit conversion exists from b to A, the result type is A. At run-time, a is first evaluated. If a is not null, a becomes the result. Otherwise, b is evaluated and converted to type A, and this becomes the result.
…A存在,从B到A的隐式转换不存在。
Otherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. Otherwise, b is evaluated and becomes the result.
…B有一个类型B,隐式转换存在于A到B之间。a的计算结果为空。因此,B应该被评估,B应该是结果。
Otherwise, a and b are incompatible, and a compile-time error occurs.
Does not happen
我错过什么了吗?
为什么期望空合并运算符返回
既然我们知道会返回
? Otherwise, if b has a type B and an implicit conversion exists from
a to B, the result type is B. At run-time, a is first evaluated. If a
is not null, a is unwrapped to type A0 (if A exists and is nullable)
and converted to type B, and this becomes the result. Otherwise, b is
evaluated and becomes the result.
存在从
实际上,如果编写
Otherwise, if b has a type B and an implicit conversion exists from a
to B, the result type is B. At run-time, a is first evaluated. If a is
not null, a is unwrapped to type A0 (if A exists and is nullable) and
converted to type B, and this becomes the result. Otherwise, b is
evaluated and becomes the result.…B的类型为B,存在从A到B的隐式转换。A是计算为空。因此,B应该被评估,B应该被评估结果。
< /块引用>你把这个解释错了。没有说明在执行
null 检查之前,已经完成了a 到B 的转换。说明转换前进行了null 检查!你的案子符合这个条件:
If a is not null, a is unwrapped to type A0 (if A exists and is
nullable) and converted to type B, and this becomes the
result.好吧,规格说明说(我改为
x 和y ,这里不太混淆):? Otherwise, if y has a type Y and an implicit conversion exists from x to Y, the result type is Y. At run-time, x is first evaluated. If x is not null, x is unwrapped to type X0 (if X exists and is nullable) and converted to type Y, and this becomes the result. Otherwise, y is evaluated and becomes the result.
这种情况发生了。首先,检查左侧的
x ,即a ,查看null 。但它本身并不是null 。然后使用左侧。然后运行隐式转换。B 型的结果是…null 。请注意,这不同于:
在这种情况下,左操作数是一个表达式(
x ,本身就是null ,结果变成了右操作数(y )。也许引用类型之间的隐式转换应该返回
null (如果和),仅当原始类型是null 时,作为一个好的实践?我想写规范的人可以这样做(但没有):
? Otherwise, if y has a type Y and an implicit conversion exists from x to Y, the result type is Y. At run-time, x is first evaluated and converted to type Y. If the output of that conversion is not null, that output becomes the result. Otherwise, y is evaluated and becomes the result.
也许这会更直观?无论转换的输入是否为
null ,它都会强制运行时调用隐式转换。如果典型的实现很快确定了null → null ,那就不应该太昂贵。我们需要关注的部分是空合并表达式的编译时类型。
Otherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. Otherwise, b is evaluated and becomes the result.
要将其放入伪代码,请执行以下操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 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);
}
...
}