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

结论

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

C# 编译器对局部变量的优化的更多相关文章

  1. 使用Lua 局部变量来优化性能,同一时候比較局部变量和全局变量

    在竞争激烈的游戏行业中,尤其页游,面对策划复杂和频繁的需求,使用脚本能够减少难度和成本.在使用Lua的过程中,会常常訪问全局变量来作为配置文件. 在訪问全局变量时,能够通过局部变量引用全局变量来优化. ...

  2. vc编译器对 除法的优化

    基本知识,7/2 和 6/2 在计算机中的商都为3.C语言的除法不等同于数学意义中的除法. C语言的除法.采用向零取整的方法. -______________0_______________+ 只有在 ...

  3. Java编译器的2点优化

    优化1 对于byte/short/char三种类型来说,如果右侧赋值的数值没有超过范围,那么javac编译器将会自动隐含地为我们补上一个(byte)(short)(char). 如果没有超过左侧的范围 ...

  4. java9的JShell小工具和编译器两种自动优化

    一.按顺序逐步执行的脚本程序: 二.编译器自动优化 1.不超数据类型范围编译器自动添加强转操作: 2.一但发生运算,byte/short/char都会自动提升为Int,当只有常量参与运算时,编译器会先 ...

  5. 【原创】Java编译器对String的优化

    首先看以下的代码: public static void main(String[] arge) { String str1 = new String("1234"); Strin ...

  6. volatile(防止编译器对代码进行优化)

    adj.易变的:无定性的:无常性的:可能急剧波动的 网络挥发性:挥发性的:不稳定的 volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了.

  7. 翻译「C++ Rvalue References Explained」C++右值引用详解 Part6:Move语义和编译器优化

    本文为第六部分,目录请参阅概述部分:http://www.cnblogs.com/harrywong/p/cpp-rvalue-references-explained-introduction.ht ...

  8. 【转】C 编译器优化过程中的 Bug

    C 编译器优化过程中的 Bug 一个朋友向我指出一个最近他们发现的 GCC 编译器优化过程(加上 -O3 选项)里的 bug,导致他们的产品出现非常诡异的行为.这使我想起以前见过的一个 GCC bug ...

  9. JVM性能优化, Part 2 ―― 编译器

    作为JVM性能优化系列文章的第2篇,本文将着重介绍Java编译器,此外还将对JIT编译器常用的一些优化措施进行讨论(参见“JVM性能优化,Part 1″中对JVM的介绍).Eva Andreasson ...

随机推荐

  1. 使用Navicat连接MySQL8.0版本报1251错误

    出现1251错误是因为,MySQL8.0版本改变了密码的验证规则caching_sha2_password,MySQL之前的版本验证规则是mysql_native_password,现在需要修改MyS ...

  2. 【FLASK】使用ORM以及类似于Django更新新增字段

    #!/usr/bin/env python # -*- coding:utf-8 -*- from sqlalchemy.ext.declarative import declarative_base ...

  3. Kafka 【的这些原理你知道吗】

    如果只是为了开发 Kafka 应用程序,或者只是在生产环境使用 Kafka,那么了解 Kafka 的内部工作原理不是必须的.不过,了解 Kafka 的内部工作原理有助于理解 Kafka 的行为,也利用 ...

  4. 深入解析Vue里函数的调用顺序介绍

    今天为大家分享一篇对vue里函数的调用顺序介绍,写的十分的全面细致,具有一定的参考价值,对此有需要的朋友可以参考学习下.如有不足之处,欢迎批评指正. method用来定义方法的,比如你@click=& ...

  5. 实验 3:Mininet 实验——测量路径的损耗率

    一.实验目的 在实验 2 的基础上进一步熟悉 Mininet 自定义拓扑脚本,以及与损耗率相关的设定;初步了解 Mininet 安装时自带的 POX 控制器脚本编写,测试路径损耗率. 二.实验任务 h ...

  6. P5911 [POI2004]PRZ (状态压缩dp+枚举子集)

    题目背景 一只队伍在爬山时碰到了雪崩,他们在逃跑时遇到了一座桥,他们要尽快的过桥. 题目描述 桥已经很旧了, 所以它不能承受太重的东西.任何时候队伍在桥上的人都不能超过一定的限制. 所以这只队伍过桥时 ...

  7. Geography's sum up

    1.世界气候: 热带草原气候,热带雨林气候,热带沙漠气候,热带草原气候 温带季风气候,温带大陆性气候,亚热带季风和湿润性气候,温带海洋性气候 寒带气候,高原山地气候. 2.亚洲气候: 1.大陆性气候分 ...

  8. Systemd的权威用法【译】

    如何使用journalctl 来观察和操作systemd的日志 介绍 systemd的一些不错的有点就是它能涉及到进程的系统的日志.对于其他日志工具,日志通常被分布到整个系统中,由不同的daemon和 ...

  9. Tensorflow学习笔记No.3

    使用tf.data加载数据 tf.data是tensorflow2.0中加入的数据加载模块,是一个非常便捷的处理数据的模块. 这里简单介绍一些tf.data的使用方法. 1.加载tensorflow中 ...

  10. Jmeter JDBC Request 使用详解

    本篇博文讲解以MySQL为例,搞懂JDBC Request中MySQL的使用方法,换成其它数据库, 如Oracle.PSQL也会很容易上手. 一.基本配置 1.首先我们先了解一下,不同数据库的驱动类和 ...