If we do
var (hello, world) = GetHelloAndWorldStrings();
if (hello == "hello" && world == "world")
Environment.Exit(0);
Does that incur any additional costs than just doing the following:
var helloAndWorld = GetHelloAndWorldStrings();
if (helloAndWorld.Hello == "hello" && helloAndWorld.World == "world")
Environment.Exit(0);
Or is it all syntatic sugar - the code that ends up being generated always uses Item1 and Item2.
They are effectively the same generated IL with only minor emitted differences, However... they would likely be jitted and optimized to exactly the same instructions.
Given
private (String hello,string world) GetHelloAndWorldStrings()
{
return ("asdsd","sadfsdf");
}
...
public int Test1()
{
var asd = GetHelloAndWorldStrings();
if (asd.hello == "hello" && asd.world == "world")
return 1;
return 0;
}
public int Test2()
{
var (hello, world) = GetHelloAndWorldStrings();
if (hello == "hello" && world == "world")
return 1;
return 0;
}
Would basically be emitted as
public int Test1()
{
ValueTuple<string, string> helloAndWorldStrings = GetHelloAndWorldStrings();
if (helloAndWorldStrings.Item1 == "hello" && helloAndWorldStrings.Item2 == "world")
{
return 1;
}
return 0;
}
public int Test2()
{
ValueTuple<string, string> helloAndWorldStrings = GetHelloAndWorldStrings();
string item = helloAndWorldStrings.Item1;
string item2 = helloAndWorldStrings.Item2;
if (item == "hello" && item2 == "world")
{
return 1;
}
return 0;
}
You can check the IL out here
Here is an example of the JIT ASM in release
C.Test1()
L0000: push ebp
L0001: mov ebp, esp
L0003: push esi
L0004: mov ecx, [0x11198648]
L000a: mov esi, [0x1119864c]
L0010: mov edx, [0x11198650]
L0016: call System.String.Equals(System.String, System.String)
L001b: test eax, eax
L001d: je short L0038
L001f: mov edx, [0x11198654]
L0025: mov ecx, esi
L0027: call System.String.Equals(System.String, System.String)
L002c: test eax, eax
L002e: je short L0038
L0030: mov eax, 1
L0035: pop esi
L0036: pop ebp
L0037: ret
L0038: xor eax, eax
L003a: pop esi
L003b: pop ebp
L003c: ret
vs
C.Test2()
L0000: push ebp
L0001: mov ebp, esp
L0003: push esi
L0004: mov ecx, [0x11198648]
L000a: mov esi, [0x1119864c]
L0010: mov edx, [0x11198650]
L0016: call System.String.Equals(System.String, System.String)
L001b: test eax, eax
L001d: je short L0038
L001f: mov edx, [0x11198654]
L0025: mov ecx, esi
L0027: call System.String.Equals(System.String, System.String)
L002c: test eax, eax
L002e: je short L0038
L0030: mov eax, 1
L0035: pop esi
L0036: pop ebp
L0037: ret
L0038: xor eax, eax
L003a: pop esi
L003b: pop ebp
L003c: ret
In short, the net gain of worrying about this.. minus 5 minutes of your life you'll never get back
There's a third option that is equivalent to the first:
public int Test3()
{
var asd = GetHelloAndWorldStrings();
if (asd == ("hello", "world"))
return 1;
return 0;
}
It equally thranslates to (sharplab.io):
public int Test3()
{
ValueTuple<string, string> helloAndWorldStrings = GetHelloAndWorldStrings();
if (helloAndWorldStrings.Item1 == "hello" && helloAndWorldStrings.Item2 == "world")
{
return 1;
}
return 0;
}
(sharplab.io)
.method public hidebysig
instance int32 Test3 () cil managed
{
// Method begins at RVA 0x2064
// Code size 47 (0x2f)
.maxstack 2
.locals init (
[0] valuetype [System.Private.CoreLib]System.ValueTuple`2<string, string>
)
IL_0000: ldarg.0
IL_0001: call instance valuetype [System.Private.CoreLib]System.ValueTuple`2<string, string> C::GetHelloAndWorldStrings()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldfld !0 valuetype [System.Private.CoreLib]System.ValueTuple`2<string, string>::Item1
IL_000d: ldstr "hello"
IL_0012: call bool [System.Private.CoreLib]System.String::op_Equality(string, string)
IL_0017: brfalse.s IL_002d
IL_0019: ldloc.0
IL_001a: ldfld !1 valuetype [System.Private.CoreLib]System.ValueTuple`2<string, string>::Item2
IL_001f: ldstr "world"
IL_0024: call bool [System.Private.CoreLib]System.String::op_Equality(string, string)
IL_0029: brfalse.s IL_002d
IL_002b: ldc.i4.1
IL_002c: ret
IL_002d: ldc.i4.0
IL_002e: ret
} // end of method C::Test3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With