在C#中解构元组的性能损失?

问题描述

如果这样做

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;
}

You can check the IL out here

以下是发布的 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;
}

(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

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...