繁体   English   中英

空合并赋值运算符的行为

[英]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://sharplab.io/#v2:CYLg1APgAgTAjAWAFBQMwAJboMLoN7LpGYZQAs6AsgBQCU+hxTUcADOgHYCGAtgKboAvOgBEAKQD2ACw4iA3Mm790AfhXCRAcT4SATgHM+80xQC

更多信息: 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"; 在返回结果方面。 但是在这两种情况下,只有在分配之前原始namenull时,您才能获得George值。 您也可以参考语言规范了解详情

您可以使用https://sharplab.io/来测试差异。 ??=??之间的区别非常小,一旦代码经过 JIT 编译,它实际上就消失了。

简而言之 :

  1. 一旦代码被编译成程序集,它是一样的。
  2. 相当于:
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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM