问题描述
如果这样做
var (hello,world) = GetHelloAndWorldStrings();
if (hello == "hello" && world == "world")
Environment.Exit(0);
除了执行以下操作之外,还会产生其他费用吗?
var helloAndWorld = GetHelloAndWorldStrings();
if (helloAndWorld.Hello == "hello" && helloAndWorld.World == "world")
Environment.Exit(0);
还是所有语法糖-最终生成的代码始终使用Item1和Item2。
解决方法
它们实际上是相同的 IL 生成的,只有很小的发射差异,但是 ...它们可能会被插入 / em>,并已优化为完全相同的指令。
给予
<body>
<div id="demo"></div>
<input type="button" value="Click Here" onclick='myFunction()'>
<script type="text/javascript">
function myFunction(){
document.getElementById("demo").innerText = "Hello World";
}
</script>
</body>
基本上将被发射为
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;
}
以下是发布的 JIT ASM 的示例
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;
}
vs
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
简而言之,担心这一点的净收益..减去生命中的5分钟,您将永远无法回来
,还有第三个选项,等同于第一个:
public int Test3()
{
var asd = GetHelloAndWorldStrings();
if (asd == ("hello","world"))
return 1;
return 0;
}
它同样翻译为(sharplab.io):
public int Test3()
{
ValueTuple<string,string> helloAndWorldStrings = GetHelloAndWorldStrings();
if (helloAndWorldStrings.Item1 == "hello" && helloAndWorldStrings.Item2 == "world")
{
return 1;
}
return 0;
}
.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