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 没有被优化掉,还是有这个方法。

总结

以上所述是小编给大家介绍的C# 循环判断会进来几次的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • C# 循环判断会进来几次的实现代码

    最近有小伙伴告诉我,在循环的判断条件只会计算一次,本金鱼不相信,于是就做了测试,本文记录我做的测试. 先来写一个简单的代码, 就一个循环,循环的判断是从一个函数获取值 class Program { static void Main(string[] args) { var meepeMorcear = new MeepeMorcear(); meepeMorcear.BirmeruLerrayjairbay(); } } class MeepeMorcear { public void Bir

  • Vue条件循环判断+计算属性+绑定样式v-bind的实例

    Vue.js条件与循环 1.条件判断 (1)v-if, <div id="app"> <p v-if="seen">现在你看到我了</p> <template v-if="ok"> <h1>菜鸟教程</h1> </template> </div> <script> new Vue({ el:'#app', data:{ seen:true,

  • JavaScript常用语句循环,判断,字符串换数字

    目录 1.switch 2.While 循环 3.Do/While 循环 3.字符串转换数字 1.switch 选择多个需被执行的代码块之一 switch(e) { case 1: //e为1执行这里 break; case 2: //e为2执行这里 break; default: //都不满足执行这里 } 注意: 不必用break中断 switch 代码块中的最后一个 case.代码块在此处会自然结束. Switch case 使用严格比较(===),值必须与要匹配的类型相同. 如果 Java

  • Python3 ID3决策树判断申请贷款是否成功的实现代码

    1. 定义生成树 # -*- coding: utf-8 -*- #生成树的函数 from numpy import * import numpy as np import pandas as pd from math import log import operator # 计算数据集的信息熵(Information Gain)增益函数(机器学习实战中信息熵叫香农熵) def calcInfoEnt(dataSet):#本题中Label即好or坏瓜 #dataSet每一列是一个属性(列末是La

  • PHP判断json格式是否正确的实现代码

    废话不多说了,直接给大家贴代码了,具体代码如下所示: <?php $GLOBALS['count'] = 0; //校验data或者content的json格式是否有错误 function data($value) { if (isset($value['data'])) { $value['data'] = json_decode($value['data'], true); } else if (isset($value['content'])) { $value['content'] =

  • Android判断是否有拍照权限的实例代码

    下面一段代码给大家介绍android判断是否有拍照权限,具体代码如下所示: /** * 返回true 表示可以使用 返回false表示不可以使用 */ public boolean cameraIsCanUse() { boolean isCanUse = true; Camera mCamera = null; try { mCamera = Camera.open(); Camera.Parameters mParameters = mCamera.getParameters(); //针对

  • 判断是否存在子节点的实现代码

    判断是否存在子节点的实现代码 Object.prototype.exist = function(){ if(typeof this !='undefined' && this.length>=1){ return true; } return false; }; 不解释. 以上这篇判断是否存在子节点的实现代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • jquery判断类型是不是number类型的实例代码

    判断获取的数据是不是number类型 var val=$("#id).val(); If(typeof val=="number"){ 是数字类型 }else{ 不是数字类型 } 以上就是小编为大家带来的jquery判断类型是不是number类型的实例代码全部内容了,希望大家多多支持我们~

  • jquery实现可自动判断位置的弹出层效果代码

    本文实例讲述了jquery实现可自动判断位置的弹出层效果代码.分享给大家供大家参考.具体如下: 这是一款jquery实现的智能弹出层效果,位置可以自适应,当层靠右边显示时自动往左移.初次运行时请按F5刷新,载入远程jQuery后才能看到效果,点击鼠标左键,弹出层将出现,在最右边点击时层自动往左移. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/jquery-auto-check-pos-alert-dlg-demo/ 具体代码如下: <!DOC

  • Android 使用SharePerference判断是否为第一次登陆的实现代码

    很多app中在第一次安装登陆时会有引导欢迎界面,第二次打开时就不再显示引导页面. 这个功能可以通过使用SharePreferences将用户的登陆信息保存起来,当app启动时判断登陆信息决定打开页面. 以下是创建的SharePreference类: public class SharePreference { Context context; public SharePreference(Context context) { this.context = context; } /****设置状态

随机推荐