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

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

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

   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 - 博客园

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

  1. C# 循环的判断会进来几次

    最近有小伙伴告诉我,在循环的判断条件只会计算一次,本金鱼不相信,于是就做了测试,本文记录我做的测试. 先来写一个简单的代码, 就一个循环,循环的判断是从一个函数获取值 class Program { ...

  2. Java 变量、循环、判断

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

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

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

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

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

  5. “全栈2019”Java多线程第九章:判断线程是否存活isAlive()详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  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. agentzh 的 Nginx 教程(版本 2019.07.31)

    agentzh 的 Nginx 教程(版本 2019.07.31) agentzh 的 Nginx 教程(版本 2019.07.31) https://openresty.org/download/a ...

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

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

随机推荐

  1. Hibernate继承注解

    hibernate应用中,继承的用途或目的主要有两点: 组件化:故明思义,把重复性的代码抽取成组件,以便重用和维护.hibernate应用中,一些重复的字段,重复的映射配置,就需要抽取成组件. 多态性 ...

  2. 洛谷p1605--迷宫 经典dfs

    https://www.luogu.org/problemnew/show/P1605 用这种题来复习一下dfs 给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过.给定起点坐标和终点坐标,问 ...

  3. ongl与Struts标签

    一.ONGL OGNL 的全称是“Object-Graph Navigation Language”,即对象图导航语言,它是一种功能强大的开源表达式语言.使用这种表达式语言可以通过某种表达式语法存取  ...

  4. Ajax和json一道基本的练习题

    关于ajax是javaEE中最基本的操作: 下面是这道题: 基本功能: jsp+servlet+ajax实现用户信息查询,实现无刷新删除 用户信息包括 学号 姓名 出生日期 性别 操作 2017010 ...

  5. react高阶函数组件

    Layout as a Higher Order Component // components/MyLayout.js import Header from './Header'; const la ...

  6. Luogu P1314 聪明的质监员(二分+前缀和)

    P1314 聪明的质监员 题意 题目描述 小\(T\)是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有\(n\)个矿石,从\(1\)到\(n\)逐一编号,每个矿石都有自己的重量\(w_i\) ...

  7. js图片碎片效果(移动端也适用)

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  8. 组合数学起步-排列计数[ZJOI2010][BZOJ2111]

    <题面> 数据范围:$1 \leq N \leq 10^6, P \leq 10^9 $ 这个题…… 以为是排列,其实是组合 题目中说是从所有排列中找到Magic的,就是 $p_{i/2} ...

  9. MAC+iTerm定制目录显示颜色和提示符

    知道该如何定制ls时各种类型文件(unix下所有的都是file..)的颜色了. 很简单,就是在.bash_profile下加了三行. export CLICOLOR=1 export LSCOLORS ...

  10. laravel-admin 自定义导出excel功能,并导出图片

    https://www.jianshu.com/p/91975f66427d 最近用laravel-admin在做一个小项目,其中用到了excel导出功能. 但是laravel-admin自带的导出功 ...