• C# 编译器对局部变量的优化


    C# 编译器对局部变量的优化

    C# 的编译器可以对代码进行优化,所以,我们在写代码的时候,可以更多地考虑一下代码的易读性问题。

    不考虑基本的对齐和换行美化。看一下局部变量优化问题。

    C# 示例代码

    例如,我们有一段如下的代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            { 
                var s = DoSomething();
                Console.WriteLine(s);
            }
    
            static string DoSomething()
            {
                var s1 = "Hello, world.";
                var s2 = s1.ToUpper();
                return s2;
            }
        }
    }
    

    在 DoSomething() 这个方法中,里面定义了两个局部变量:

    • s1
    • s2

    在 Main() 方法中,定义了一个局部变量:

    • s

    定义 s1 和 s2 是为了提高代码的可读性,它们会导致生成冗余的代码,降低执行效率吗?

    我们分别在 Debug 模式下和 Release 模式下进行编译,使用 ILDasm 查看生成的中间代码。

    Debug 模式下生成的中间代码

    在 Debug 下编译之后,DoSomething() 生成的中间代码如下,可以看到实际上有 3 个局部变量。除了我们自己定义的 s1 和 s2 之外,还有一个生成的 V_2,代码的尺寸为 20。

    .method private hidebysig static string  DoSomething() cil managed
    {
      // Code size       20 (0x14)
      .maxstack  1
      .locals init ([0] string s1,
               [1] string s2,
               [2] string V_2)
      IL_0000:  nop
      IL_0001:  ldstr      "Hello, world."
      IL_0006:  stloc.0
      IL_0007:  ldloc.0
      IL_0008:  callvirt   instance string [mscorlib]System.String::ToUpper()
      IL_000d:  stloc.1
      IL_000e:  ldloc.1
      IL_000f:  stloc.2
      IL_0010:  br.s       IL_0012
      IL_0012:  ldloc.2
      IL_0013:  ret
    } // end of method Program::DoSomething
    

    看一下 Main() 方法。

    有我们定义的 s 这一个局部变量,代码尺寸为 15 个字节。

    .method private hidebysig static void  Main(string[] args) cil managed
    {
      .entrypoint
      // Code size       15 (0xf)
      .maxstack  1
      .locals init ([0] string s)
      IL_0000:  nop
      IL_0001:  call       string ConsoleApp1.Program::DoSomething()
      IL_0006:  stloc.0
      IL_0007:  ldloc.0
      IL_0008:  call       void [mscorlib]System.Console::WriteLine(string)
      IL_000d:  nop
      IL_000e:  ret
    } // end of method Program::Main
    

    Release 模式下生成的中间代码

    而在 Release 模式下,实际上,DoSomething() 中所有的局部变量都被优化掉了。代码尺寸也只有 11 个字节。

    .method private hidebysig static string  DoSomething() cil managed
    {
      // Code size       11 (0xb)
      .maxstack  8
      IL_0000:  ldstr      "Hello, world."
      IL_0005:  callvirt   instance string [mscorlib]System.String::ToUpper()
      IL_000a:  ret
    } // end of method Program::DoSomething
    

    还可以看一下 Main() 方法,这个局部变量 s 也被优化掉了。代码尺寸也只有 11 字节了。

    .method private hidebysig static void  Main(string[] args) cil managed
    {
      .entrypoint
      // Code size       11 (0xb)
      .maxstack  8
      IL_0000:  call       string ConsoleApp1.Program::DoSomething()
      IL_0005:  call       void [mscorlib]System.Console::WriteLine(string)
      IL_000a:  ret
    } // end of method Program::Main
    

    结论

    编译器会尽可能对代码进行优化,我们可以为了提高代码的易读性增加一些局部变量,这并不会导致生成冗余代码并导致执行性能的下降。

  • 相关阅读:
    (转 )Unity对Lua的编辑器拓展
    unity timeline
    unity拖尾粒子问题
    unity shader 波动圈
    linux教程
    Unity Shader 基础
    ugui拖拽
    unity shader 热扭曲 (屏幕后处理)
    英文取名神器
    lua正则表达式替换字符串
  • 原文地址:https://www.cnblogs.com/haogj/p/13889976.html
Copyright © 2020-2023  润新知