Reputation: 1416
I just wonder that how ??= operator runs in the background. I have two questions about it.
Consider the following example,
string name = "John";
name ??= "George";
1) Is it equal to name = name ?? "George";
2) Does it work like this,
if (name == null) {
name = "George";
}
or
if (name == null) {
name = "George";
}
else {
name = name;
}
Upvotes: 6
Views: 1298
Reputation: 39966
It will be evaluated to this:
string text = "John";
if (text == null)
{
text = "George";
}
You can use the sharplab
to see what happens actually:
Further Info: https://stackoverflow.com/a/59300172/2946329
Based on the documentation:
C# 8.0 introduces the null-coalescing assignment operator ??=. You can use the ??= operator to assign the value of its right-hand operand to its left-hand operand only if the left-hand operand evaluates to null.
Upvotes: 10
Reputation: 131631
You can use https://sharplab.io/ to test for differences. The difference between ??=
and ??
is very small, and actually disappears once the code is JIT-compiled.
In short :
if (text == null){
text = "George";
}
SharpLab Examples
The code for this example :
public void M1() {
string name = "John";
name ??= "George";
Console.WriteLine(name);
}
public void M2() {
string name = "John";
name = name ?? "George";
Console.WriteLine(name);
}
Generates this intermediate C# code, that shows a real difference :
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);
}
The IL though is almost the same, except for a dup
(copy) and pop
operation. You'd think that ??
is somewhat slower for this :
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
vs
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
BUT the assembly in Release mode is identical:
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
Upvotes: 1
Reputation: 23268
According to documentation
null-coalescing assignment operator
??=
assigns the value of its right-hand operand to its left-hand operand only if the left-hand operand evaluates tonull
. The??=
operator doesn't evaluate its right-hand operand if the left-hand operand evaluates to non-null.
In you code sample it won't be evaluated, since name
isn't null
string name = "John";
name ??= "George";
It will work if you write something like that
string name = null;
name ??= "George";
Name value will be George
. Expanded variant is
if (name is null) //or name == null
{
name = "George";
}
The null-coalescing operator
??
returns the value of left-hand operand if it isn'tnull
; otherwise, it evaluates the right-hand operand and returns result.
In this sample name = name ?? "George"
the result will be George
only when name has null
value before. I your sample name = name ?? "George";
is equal to name ??= "George";
in terms of return result. But in both cases you can get a George
value only when original name
is null
before assigning. You can also refer to language specification for details
Upvotes: 3