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



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

   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. Directx11教程(66) D3D11屏幕文本输出(1)

    原文:Directx11教程(66) D3D11屏幕文本输出(1)      在D3D10中,通过ID3DX10Font接口对象,我们可以方便的在屏幕上输出文字信息,一个DrawText函数就能解决所 ...

  2. 洛谷 P3958 奶酪 并查集

    目录 题面 题目链接 题面 题目描述 输入输出格式 输入格式 输出格式: 输入输出样例 输入样例 输出样例 说明 思路 AC代码 总结 题面 题目链接 P3958 奶酪 题面 题目描述 现有一块大奶酪 ...

  3. Flask第一篇

    一. Python 现阶段三大主流Web框架 Django Tornado Flask 对比 1.Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, 不 ...

  4. Mybatis通过工具类根据用户名查找用户列表

    抽取SqlSessionFactoryUtils工具类,共享SqlSessionFactory创建过程 /** * SqlSessionFactory工具类 * @author:Mr.Tan * @C ...

  5. install tushare in python 3.6

    install tushare (D:\Anaconda3) C:\Users\Administrator>pip install tushare Collecting tushare Down ...

  6. Flask学习之十二 使用boostrap

    英文博客地址:http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xii-facelift 中文翻译地址:http://w ...

  7. 详解Python中内置的NotImplemented类型的用法

    它是什么? ? 1 2 >>> type(NotImplemented) <type 'NotImplementedType'> NotImplemented 是Pyth ...

  8. Spring AOP 的实现 原理

    反射实现 AOP 动态代理模式实例说明(Spring AOP 的实现 原理)   比如说,我们现在要开发的一个应用里面有很多的业务方法,但是,我们现在要对这个方法的执行做全面监控,或部分监控.也许我们 ...

  9. Android 字体库的使用

    开发Android的人大多都知道,Android里面对字体的支持少得可怜,默认情况下,TextView  的 typeface 属性支持 "Sans","serif&qu ...

  10. springboot&mybatis 增删改查系列(一)

    创建父项目 首先,我们需要创建一个Maven项目. 在这个项目的pom文件中加入以下几个依赖: <!-- spring boot --> <parent> <groupI ...