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 没有被优化掉,还是有这个方法。
我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新
如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。
C# 循环的判断会进来几次的更多相关文章
- 2019-8-31-C#-循环的判断会进来几次
title author date CreateTime categories C# 循环的判断会进来几次 lindexi 2019-08-31 16:55:58 +0800 2018-06-14 0 ...
- python基本数据类型和循环、判断
一.语言分为2种: 编译型语言:写完代码不能执行,得先编译 c.c++.c#,速度相对解释性语言更快,因为只需要执行一次解释型语言:不需要编译,直接执行 python.java.php.js.go.r ...
- mysql存储过程查询结果循环遍历 判断 赋值 游标等基本操作
一.首先说下本篇博客所实现功能的背景和功能是怎样的: 背景:因为公司项目开始迁移新平台项目,所以以前的平台老数据以及订单信息需要拆分表,而且需要业务逻辑来分析以前的订单表,来拆分成另外的几个新表,包括 ...
- Java 变量、循环、判断
粗糙笔记不喜勿喷 Java 8大基本类型 第一类:逻辑型(boolean) 1.boolean类型只存在true(真),false(假)两种形式 例: boolean a=true; boolean ...
- Angular4.x 创建组件|绑定数据|绑定属性|数据循环|条件判断|事件|表单处理|双向数据绑定
Angular4.x 创建组件|绑定数据|绑定属性|数据循环|条件判断|事件|表单处理|双向数据绑定 创建 angular 组件 https://github.com/angular/angular- ...
- smarty基本用法,循环,判断
require './smarty/Smarty.class.php'; $sm = new Smarty; $sm->setTemplateDir("./dir");//设 ...
- .NET Core CSharp初级篇 1-2 循环与判断
.NET Core CSharp初级篇 1-2 本节内容循环与判断 循环 循环是一个在任何语言都是极为重要的语法,它可以用于很多东西,例如迭代数组等等.在C#中,语法层面的循环有:for , fore ...
- Beego模板 循环和判断几个例子
Beego模板 循环和判断几个例子 Beego的前端几乎是另一种语言.一些循环.判断,不细看文档真的做不出来. 0. Beego的View模板语法规则: beego前端(view)统一使用了 {{ 和 ...
- 大爽Python入门教程 1-3 简单的循环与判断
大爽Python入门公开课教案 点击查看教程总目录 这里只初步认识下循环和判断,以便于我们去实现一些简单的计算. 循环和判断的详细知识和细节,我们将在后面的章节(大概是第三章)展开阐述. 1 初步了解 ...
随机推荐
- 【OI】二分图最大匹配
所谓二分图,是可以分为两个点集的图: 所谓二分图最大匹配,是两个点集之间,每两个不同点集的点连接,每个点只能连一个点,最大的连接数就是最大匹配. 如何解最大匹配,需要用到匈牙利算法. 另:本文写了很多 ...
- 仿Google Nexus菜单样式
在线演示 本地下载
- objectarx之两条曲线最短距离
double CCommonFuntion::GetLineDistance(AcDbObjectId& Line1, AcDbObjectId& Line2){ AcGeLineSe ...
- php刷新当前页面,js刷新页面
echo "<script language=JavaScript> location.replace(location.href);</script>"; ...
- RNN与 LSTM 网络
循环神经网络(RNN) 人们的每次思考并不都是从零开始的.比如说你在阅读这篇文章时,你基于对前面的文字的理解来理解你目前阅读到的文字,而不是每读到一个文字时,都抛弃掉前面的思考,从头开始.你的记忆是有 ...
- 集合 Enumerable Enumerator yield
集合: 通过索引来访问成员,--引申到索引器 的使用 for foreach循环遍历 --引申到 IEnumerable IEnumerator(会引申到yield) 常用的集合操作,add, ins ...
- LeetCode115 Distinct Subsequences
Given a string S and a string T, count the number of distinct subsequences of T in S. (Hard) A subse ...
- BackgroundWorker 的输入、输出参数、进度条与文字刷新、取消机制、返回事件
1. 定义全局变量 BackgroundWorker backgroundwoker; 2. 点击开始按钮或其它时机初始化 backgroundwoker = new BackgroundWorker ...
- Gym - 101620H_Hidden Hierarchy(树+模拟)
Hidden Hierarchy 题目链接 题目描述 You are working on the user interface for a simple text-based file explor ...
- LeetCode Weekly Contest 6
leetcode现在每周末举办比赛,这是今天上午参加的比赛的题解.题目难度不算大,两个easy,一个medium,一个hard.hard题之前接触过,所以做得比较顺利. 1. Sum of Left ...