[英]The behavior of null-coalescing assignment operator
我只是想知道??=运算符如何在后台运行。 我有两个问题。
考虑下面的例子,
string name = "John";
name ??= "George";
1)是否等于name = name ?? "George";
name = name ?? "George";
2)它是这样工作的吗,
if (name == null) {
name = "George";
}
或者
if (name == null) {
name = "George";
}
else {
name = name;
}
它将被评估为:
string text = "John";
if (text == null)
{
text = "George";
}
您可以使用sharplab
查看实际发生的情况:
更多信息: https : //stackoverflow.com/a/59300172/2946329
基于文档:
C# 8.0 引入了空合并赋值运算符 ??=。 仅当左侧操作数的计算结果为 null 时,您才可以使用 ??= 运算符将其右侧操作数的值分配给其左侧操作数。
根据文档
空合并赋值运算符
??=
仅当左侧操作数的计算结果为null
时才将其右侧操作数的值分配给其左侧操作数。 如果左侧操作数的计算结果为非空,则??=
运算符不会计算其右侧操作数。
在您的代码示例中,它不会被评估,因为name
不为null
string name = "John";
name ??= "George";
如果你写这样的东西它会起作用
string name = null;
name ??= "George";
名称值为George
。 扩展变体是
if (name is null) //or name == null
{
name = "George";
}
空合并运算符
??
如果左操作数不为null
,则返回其值; 否则,它评估右侧操作数并返回结果。
在此示例中name = name ?? "George"
name = name ?? "George"
只有在 name 之前为null
值时,结果才会是George
。 我您的样品name = name ?? "George";
name = name ?? "George";
等于name ??= "George";
在返回结果方面。 但是在这两种情况下,只有在分配之前原始name
为null
时,您才能获得George
值。 您也可以参考语言规范了解详情
您可以使用https://sharplab.io/来测试差异。 ??=
和??
之间的区别非常小,一旦代码经过 JIT 编译,它实际上就消失了。
简而言之 :
if (text == null){
text = "George";
}
SharpLab 示例
这个例子的代码:
public void M1() {
string name = "John";
name ??= "George";
Console.WriteLine(name);
}
public void M2() {
string name = "John";
name = name ?? "George";
Console.WriteLine(name);
}
生成这个中间 C# 代码,它显示了真正的区别:
public void M1()
{
string text = "John";
if (text == null)
{
text = "George";
}
Console.WriteLine(text);
}
public void M2()
{
string text = "John";
text = (text ?? "George");
Console.WriteLine(text);
}
除了dup
(复制)和pop
操作外,IL 几乎相同。 你会认为??
这有点慢:
IL_0000: nop
IL_0001: ldstr "John"
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: brtrue.s IL_0010
IL_000a: ldstr "George"
IL_000f: stloc.0
IL_0010: ldloc.0
IL_0011: call void [System.Console]System.Console::WriteLine(string)
IL_0016: nop
IL_0017: ret
对比
IL_0000: nop
IL_0001: ldstr "John"
IL_0006: stloc.0
IL_0007: ldloc.0
*** IL_0008: dup
IL_0009: brtrue.s IL_0011
*** IL_000b: pop
IL_000c: ldstr "George"
IL_0011: stloc.0
IL_0012: ldloc.0
IL_0013: call void [System.Console]System.Console::WriteLine(string)
IL_0018: nop
IL_0019: ret
但是发布模式下的程序集是相同的:
C.M1()
L0000: mov ecx, [0x1a58b46c]
L0006: test ecx, ecx
L0008: jnz L0010
L000a: mov ecx, [0x1a58b470]
L0010: call System.Console.WriteLine(System.String)
L0015: ret
C.M2()
L0000: mov ecx, [0x1a58b46c]
L0006: test ecx, ecx
L0008: jnz L0010
L000a: mov ecx, [0x1a58b470]
L0010: call System.Console.WriteLine(System.String)
L0015: ret
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.