最近有小伙伴告诉我,在循环的判断条件只会计算一次,本金鱼不相信,于是就做了测试,本文记录我做的测试。



先来写一个简单的代码, 就一个循环,循环的判断是从一个函数获取值

   class Program
{
static void Main(string[] args)
{
var meepeMorcear = new MeepeMorcear();
meepeMorcear.BirmeruLerrayjairbay();
}
} class MeepeMorcear
{
public void BirmeruLerrayjairbay()
{
for (int i = 0; i < DaydrearNenawerlai(); i++)
{
Console.WriteLine("第" +i.ToString()+"个逗比");
}
} public int DaydrearNenawerlai()
{
Console.WriteLine("进入");
return 10;
}
}

通过 Main 调用 BirmeruLerrayjairbay ,这个函数里面的 for 判断是 DaydrearNenawerlai 拿到一个值,我尝试在 release 运行,结果每个判断都需要进入 DaydrearNenawerlai 函数,请看输出

进入
第0个逗比
进入
第1个逗比
进入
第2个逗比
进入
第3个逗比
进入
第4个逗比
进入
第5个逗比
进入
第6个逗比
进入
第7个逗比
进入
第8个逗比
进入
第9个逗比

也就是在 Debug 或 Release 下,for 里面的判断都是需要执行,所以在 for 里的判断如果写了很长的计算,那么就会在每次循环都需要重新计算。即使每次计算出来的值都是一样,也需要重新计算。

所以这样看起来性能不如这样写,使用一个临时的变量获取判断的值

        public void BirmeruLerrayjairbay()
{
var mowraiTepalor = DaydrearNenawerlai();
for (int i = 0; i < mowraiTepalor; i++)
{
Console.WriteLine("第" +i.ToString()+"个逗比");
}
}

但是很快,另一个小伙伴告诉我,你把输出去掉,然后使用断点,你再看看

我添加了断点,在断点输出 123 然后运行

这时我发现运行没有输出 123 也就是函数没有进来,我再次添加断点,跟着函数也没有访问

所以这时的 DaydrearNenawerlai 函数就被优化掉了

我和一个小伙伴说了这个问题,他说是被 IL 优化了,我一点不相信,所以我就去看 IL 代码

从下面的代码

        public void BirmeruLerrayjairbay()
{
for (int i = 0; i < DaydrearNenawerlai(); i++)
{
Console.WriteLine("第" +i.ToString()+"个逗比");
}
} /// <summary>
/// 进入lindexi.github.io可以看到更多博客
/// </summary>
/// <returns></returns>
public static int DaydrearNenawerlai()
{
return 10;
}

转 IL 可以看到下面代码,我会在 IL 添加很多注释,所以很容易看懂。

  .method public hidebysig instance void
BirmeruLerrayjairbay() cil managed
{
.maxstack 3
.locals init (
[0] int32 i
) // 第 23 行 18 个字符到 27 个字符
// [23 18 - 23 27]
IL_0000: ldc.i4.0
// 定义 i ,代码的 int i = 0;
IL_0001: stloc.0 // i IL_0002: br.s IL_0023
// 这里就是进入循环 for ,在 IL 不管 for 还是 while 都是差不多
// start of loop, entry point: IL_0023 // [25 17 - 25 60]
// 下面这个代码就是 Console.WriteLine("第" +i.ToString()+"个逗比"); 从代码可以看到
// 需要先申请"第"
IL_0004: ldstr "第"
// 然后把 i 放入栈
IL_0009: ldloca.s i
// 调用 int.ToString ,使用的是实例的方法
IL_000b: call instance string [mscorlib]System.Int32::ToString()
// 把"个逗比"放入栈
IL_0010: ldstr "个逗比"
// 调用字符串组合方法,组合三个字符串,返回一个字符串。
// 把刚才入栈三个字符串出栈,返回的字符串入栈
IL_0015: call string [mscorlib]System.String::Concat(string, string, string)
// 调用 Console.WriteLine ,从栈拿到一个字符串输出
IL_001a: call void [mscorlib]System.Console::WriteLine(string) // 下面是 i++ 代码
// [23 55 - 23 58]
// 将指定索引处的局部变量加载到计算堆栈上,这里的索引是 0 ,在代码的变量是 i 所以把 i 加载到计算堆栈
IL_001f: ldloc.0 // i
// 将整数值 1 作为 int32 推送到计算堆栈上
IL_0020: ldc.i4.1
// 从堆栈出栈两个数值进行相加,返回的值放在栈
IL_0021: add
// 从计算堆栈的顶部弹出当前值并将其存储到指定索引处的局部变量列表中,这里索引是 0 ,在代码的变量是 i ,所以 i = i + 1 的代码就是这样做
IL_0022: stloc.0 // i // 从堆栈加载 i ,把 i 入栈
// [23 29 - 23 53]
IL_0023: ldloc.0 // i
// 调用方法 DaydrearNenawerlai 拿到返回值
IL_0024: call int32 MuhoubearWhedoofi.MeepeMorcear::DaydrearNenawerlai()
// 如果第一个值小于第二个值,则将控制转移到目标指令,这里的第一个值就是 i ,第二个值就是 DaydrearNenawerlai 的返回值。跳转到标签 IL_0004 ,如果没有小于,就继续代码。
IL_0029: blt.s IL_0004
// end of loop // [27 9 - 27 10]
IL_002b: ret } // end of method MeepeMorcear::BirmeruLerrayjairbay .method public hidebysig static int32
DaydrearNenawerlai() cil managed
{
.maxstack 8 // 把一个值 放入堆栈,放入的是 10 ,然后从栈拿到值返回
// [36 13 - 36 23]
IL_0000: ldc.i4.s 10 // 0x0a
IL_0002: ret } // end of method MeepeMorcear::DaydrearNenawerlai

从上面代码可以发现,实际 DaydrearNenawerlai 没有被优化掉,还是有这个方法。

参见:.net IL 指令速查 - 飞鸟123 - 博客园

我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系

C# 循环的判断会进来几次的更多相关文章

  1. 2019-8-31-C#-循环的判断会进来几次

    title author date CreateTime categories C# 循环的判断会进来几次 lindexi 2019-08-31 16:55:58 +0800 2018-06-14 0 ...

  2. python基本数据类型和循环、判断

    一.语言分为2种: 编译型语言:写完代码不能执行,得先编译 c.c++.c#,速度相对解释性语言更快,因为只需要执行一次解释型语言:不需要编译,直接执行 python.java.php.js.go.r ...

  3. mysql存储过程查询结果循环遍历 判断 赋值 游标等基本操作

    一.首先说下本篇博客所实现功能的背景和功能是怎样的: 背景:因为公司项目开始迁移新平台项目,所以以前的平台老数据以及订单信息需要拆分表,而且需要业务逻辑来分析以前的订单表,来拆分成另外的几个新表,包括 ...

  4. Java 变量、循环、判断

    粗糙笔记不喜勿喷 Java 8大基本类型 第一类:逻辑型(boolean) 1.boolean类型只存在true(真),false(假)两种形式 例: boolean a=true; boolean ...

  5. Angular4.x 创建组件|绑定数据|绑定属性|数据循环|条件判断|事件|表单处理|双向数据绑定

    Angular4.x 创建组件|绑定数据|绑定属性|数据循环|条件判断|事件|表单处理|双向数据绑定 创建 angular 组件 https://github.com/angular/angular- ...

  6. smarty基本用法,循环,判断

    require './smarty/Smarty.class.php'; $sm = new Smarty; $sm->setTemplateDir("./dir");//设 ...

  7. .NET Core CSharp初级篇 1-2 循环与判断

    .NET Core CSharp初级篇 1-2 本节内容循环与判断 循环 循环是一个在任何语言都是极为重要的语法,它可以用于很多东西,例如迭代数组等等.在C#中,语法层面的循环有:for , fore ...

  8. Beego模板 循环和判断几个例子

    Beego模板 循环和判断几个例子 Beego的前端几乎是另一种语言.一些循环.判断,不细看文档真的做不出来. 0. Beego的View模板语法规则: beego前端(view)统一使用了 {{ 和 ...

  9. 大爽Python入门教程 1-3 简单的循环与判断

    大爽Python入门公开课教案 点击查看教程总目录 这里只初步认识下循环和判断,以便于我们去实现一些简单的计算. 循环和判断的详细知识和细节,我们将在后面的章节(大概是第三章)展开阐述. 1 初步了解 ...

随机推荐

  1. iOS 9 学习系列:Storyboard References

    http://www.cocoachina.com/ios/20150922/13474.html 如果你曾经使用 interface builder 创建过一个复杂.界面非常多的应用,你就会明白最后 ...

  2. 快速启动Oracle服务

    快速启动Oracle服务的批处理命令步骤 新建记事本 粘贴如下内容: @echo off echo 确定要启动Oracle 11g服务吗? pause net start OracleOraDb11g ...

  3. MyBatis映射文件的基本功能

    #{}与${}区别 "#{}"使用的是preparedStatement方式预处理,就是使用了占位符来填充数据防止SQL注入. ${}使用的是statement方式进行sql语句的 ...

  4. jQuery 五角星评分

    五角星打分 我用的是搜狗输入法上带的特殊符号打出来的  空五角星:☆  实五角星:★ 1.html <ul class="comment"> <li>☆&l ...

  5. genymotion 和genymotion eclipse 插件安装 !

    昨天天有好心网友在群里共享了一个好用的 android 模拟器 genymotion 昨天就试用了下 真心流畅 各位不妨一试 http://www.genymotion.com/ doc https: ...

  6. vue element 中自定义传值

    一直以来都不知道如何传自定义的值,一直只会默认的,今天终于找到方法了. 比如这个上传图片的控件,想带当前的index过去,就这样写.其它的类似 :http-request="(file,fi ...

  7. 第三期 行为规划——4.形式化FSM

    让我们考虑一个简单的自动售货机,其中一切花费20美分.假设这台自动售货机只需要镍和硬币,但没有更大或更小. 然后,我们可以模拟状态这台自动售货机以已存入的金额为准.起始状态将为零美分.有两种可能发生. ...

  8. behavior planning——inputs to transition functions

    the answer is that we have to pass all  of the data into transition function except for the previous ...

  9. linux lvm删除导致无法启动

    要想编辑/etc/fstab文件,我们需要在系统中重新挂载根目录,使其具有可读写状态,使用如下命令: mount -o remount,rw / 该条命令的作用是,以可读写的形式重新挂载根分区. 然后 ...

  10. 一文告诉你Adam、AdamW、Amsgrad区别和联系 重点

    **序言:**Adam自2014年出现之后,一直是受人追捧的参数训练神器,但最近越来越多的文章指出:Adam存在很多问题,效果甚至没有简单的SGD + Momentum好.因此,出现了很多改进的版本, ...