编译器,编译器处理while,for结构的小发现

在做一个日报自动报表发送项目时,因为项目是Windows服务,而且报表是每天自动发送,所以里面有这么一个函数
public void AutoReportSend() { while (true) { try { //采集时间没到,则结束。直到采集时间才开始采集作业 if (DateTime.Now < SystemConfiguration.GetInstance().GatherTime) { Thread.Sleep((TimeSpan)(SystemConfiguration.GetInstance().GatherTime - DateTime.Now)); } log.Info("邮件发送开始!"); ReportDataProcess model = new ReportDataProcess(); model.GenerateReport(); EmailUtil emailUtil = new EmailUtil(); string filePath = ConfigurationSettings.AppSettings["filePath"].ToString(); string fileName = ConfigurationSettings.AppSettings["fileName"].ToString(); emailUtil.IsBodyHtml = true; emailUtil.EmailTitle = DateTime.Now.ToString("yyyy") + "年" + DateTime.Now.Month.ToString() + "月" + DateTime.Now.Day.ToString() + "日" + ConfigurationSettings.AppSettings["EmailTitle"].ToString(); emailUtil.EmSubject = ConfigurationSettings.AppSettings["EmSubject"].ToString(); emailUtil.SendEmilPerson = ConfigurationSettings.AppSettings["SendEmil"].ToString(); emailUtil.ToEmail = ConfigurationSettings.AppSettings["ToEmail"].ToString(); emailUtil.FromEmail = ConfigurationSettings.AppSettings["SendEmil"].ToString(); emailUtil.SendEmailAcount = ConfigurationSettings.AppSettings["SendEmailAcount"].ToString(); emailUtil.SendEmailPsd = ConfigurationSettings.AppSettings["SendEmialPswd"].ToString(); emailUtil.SetEmailAttactment(fileName, filePath); emailUtil.SmtpHost = ConfigurationSettings.AppSettings["SmtpHost"].ToString(); emailUtil.SmtpServePort = ConfigurationSettings.AppSettings["SmtpServePort"].ToString(); emailUtil.EmailContent = ConfigurationSettings.AppSettings["EmailContent"].ToString(); emailUtil.SendEmail(); log.Info("邮件发送成功!"); DateTime dtNow = DateTime.Now; DateTime dtNext = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " " + SystemConfiguration.GetInstance().GatherHour + ":" + SystemConfiguration.GetInstance().GatherMinute); Thread.Sleep((TimeSpan)(dtNext.AddDays(1) - dtNow)); } catch (Exception exc) { log.Error(exc.ToString()); //发送报错短信 SendMessage.MessageSending("函数AutoReportSend 出错,具体情况请检查日志"); Thread.Sleep(600000); } } }


偶然情况下让我发现了一个让我觉得比较有趣的问题:我用.NET Reflector工具查看项目的exe文件时候,发现里面的这段代码变成了下面的样子
编译器,编译器处理while,for结构的小发现编译器,编译器处理while,for结构的小发现代码 public void AutoReportSend() { Label_0000: try { if (DateTime.Now < SystemConfiguration.GetInstance().GatherTime) { Thread.Sleep((TimeSpan) (SystemConfiguration.GetInstance().GatherTime - DateTime.Now)); } log.Info("邮件发送开始!"); new ReportDataProcess().GenerateReport(); EmailUtil emailUtil = new EmailUtil(); string filePath = ConfigurationSettings.AppSettings["filePath"].ToString(); string fileName = ConfigurationSettings.AppSettings["fileName"].ToString(); emailUtil.set_IsBodyHtml(true); emailUtil.set_EmailTitle(DateTime.Now.ToString("yyyy") + "年" + DateTime.Now.Month.ToString() + "月" + DateTime.Now.Day.ToString() + "日" + ConfigurationSettings.AppSettings["EmailTitle"].ToString()); emailUtil.set_EmSubject(ConfigurationSettings.AppSettings["EmSubject"].ToString()); emailUtil.set_SendEmilPerson(ConfigurationSettings.AppSettings["SendEmil"].ToString()); emailUtil.set_ToEmail(ConfigurationSettings.AppSettings["ToEmail"].ToString()); emailUtil.set_FromEmail(ConfigurationSettings.AppSettings["SendEmil"].ToString()); emailUtil.set_SendEmailAcount(ConfigurationSettings.AppSettings["SendEmailAcount"].ToString()); emailUtil.set_SendEmailPsd(ConfigurationSettings.AppSettings["SendEmialPswd"].ToString()); emailUtil.SetEmailAttactment(fileName, filePath); emailUtil.set_SmtpHost(ConfigurationSettings.AppSettings["SmtpHost"].ToString()); emailUtil.set_SmtpServePort(ConfigurationSettings.AppSettings["SmtpServePort"].ToString()); emailUtil.set_EmailContent(ConfigurationSettings.AppSettings["EmailContent"].ToString()); emailUtil.SendEmail(); log.Info("邮件发送成功!"); DateTime dtNow = DateTime.Now; Thread.Sleep((TimeSpan) (Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " " + SystemConfiguration.GetInstance().GatherHour + ":" + SystemConfiguration.GetInstance().GatherMinute).AddDays(1.0) - dtNow)); goto Label_0000; } catch (Exception exc) { log.Error(exc.ToString()); SendMessage.MessageSending("函数AutoReportSend 出错,具体情况请检查日志"); Thread.Sleep(0x927c0); goto Label_0000; } }

反编译的IL代码如下:
代码 1 .method public hidebysig instance void AutoReportSend() cil managed 2 { 3 .maxstack 5 4 .locals init ( 5 [0] class [GSP.Bll.ThreeCountry]GSP.Bll.ThreeCountry.ReportDataProcess model, 6 [1] class [GSP.Common]GSP.Common.Utils.EmailUtil emailUtil, 7 [2] string filePath, 8 [3] string fileName, 9 [4] valuetype [mscorlib]System.DateTime dtNow, 10 [5] valuetype [mscorlib]System.DateTime dtNext, 11 [6] class [mscorlib]System.Exception exc, 12 [7] string[] CS$0$0000, 13 [8] valuetype [mscorlib]System.DateTime CS$0$0001, 14 [9] valuetype [mscorlib]System.DateTime CS$0$0002, 15 [10] int32 CS$0$0003, 16 [11] valuetype [mscorlib]System.DateTime CS$0$0004, 17 [12] int32 CS$0$0005, 18 [13] string[] CS$0$0006, 19 [14] valuetype [mscorlib]System.DateTime CS$0$0007) 20 L_0000: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now() 21 L_0005: call class ExcelAutoReport.SystemConfiguration ExcelAutoReport.SystemConfiguration::GetInstance() 22 L_000a: callvirt instance valuetype [mscorlib]System.DateTime ExcelAutoReport.SystemConfiguration::get_GatherTime() 23 L_000f: call bool [mscorlib]System.DateTime::op_LessThan(valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime) 24 L_0014: brfalse.s L_002f 25 L_0016: call class ExcelAutoReport.SystemConfiguration ExcelAutoReport.SystemConfiguration::GetInstance() 26 L_001b: callvirt instance valuetype [mscorlib]System.DateTime ExcelAutoReport.SystemConfiguration::get_GatherTime() 27 L_0020: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now() 28 L_0025: call valuetype [mscorlib]System.TimeSpan [mscorlib]System.DateTime::op_Subtraction(valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime) 29 L_002a: call void [mscorlib]System.Threading.Thread::Sleep(valuetype [mscorlib]System.TimeSpan) 30 L_002f: ldsfld class [log4net]log4net.ILog ExcelAutoReport.SftxExcelAutoReport::log 31 L_0034: ldstr "\u90ae\u4ef6\u53d1\u9001\u5f00\u59cb\uff01" 32 L_0039: callvirt instance void [log4net]log4net.ILog::Info(object) 33 L_003e: newobj instance void [GSP.Bll.ThreeCountry]GSP.Bll.ThreeCountry.ReportDataProcess::.ctor() 34 L_0043: stloc.0 35 L_0044: ldloc.0 36 L_0045: callvirt instance void [GSP.Bll.ThreeCountry]GSP.Bll.ThreeCountry.ReportDataProcess::GenerateReport() 37 L_004a: newobj instance void [GSP.Common]GSP.Common.Utils.EmailUtil::.ctor() 38 L_004f: stloc.1 39 L_0050: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 40 L_0055: ldstr "filePath" 41 L_005a: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 42 L_005f: callvirt instance string [mscorlib]System.Object::ToString() 43 L_0064: stloc.2 44 L_0065: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 45 L_006a: ldstr "fileName" 46 L_006f: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 47 L_0074: callvirt instance string [mscorlib]System.Object::ToString() 48 L_0079: stloc.3 49 L_007a: ldloc.1 50 L_007b: ldc.i4.1 51 L_007c: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_IsBodyHtml(bool) 52 L_0081: ldloc.1 53 L_0082: ldc.i4.7 54 L_0083: newarr string 55 L_0088: stloc.s CS$0$0000 56 L_008a: ldloc.s CS$0$0000 57 L_008c: ldc.i4.0 58 L_008d: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now() 59 L_0092: stloc.s CS$0$0001 60 L_0094: ldloca.s CS$0$0001 61 L_0096: ldstr "yyyy" 62 L_009b: call instance string [mscorlib]System.DateTime::ToString(string) 63 L_00a0: stelem.ref 64 L_00a1: ldloc.s CS$0$0000 65 L_00a3: ldc.i4.1 66 L_00a4: ldstr "\u5e74" 67 L_00a9: stelem.ref 68 L_00aa: ldloc.s CS$0$0000 69 L_00ac: ldc.i4.2 70 L_00ad: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now() 71 L_00b2: stloc.s CS$0$0002 72 L_00b4: ldloca.s CS$0$0002 73 L_00b6: call instance int32 [mscorlib]System.DateTime::get_Month() 74 L_00bb: stloc.s CS$0$0003 75 L_00bd: ldloca.s CS$0$0003 76 L_00bf: call instance string [mscorlib]System.Int32::ToString() 77 L_00c4: stelem.ref 78 L_00c5: ldloc.s CS$0$0000 79 L_00c7: ldc.i4.3 80 L_00c8: ldstr "\u6708" 81 L_00cd: stelem.ref 82 L_00ce: ldloc.s CS$0$0000 83 L_00d0: ldc.i4.4 84 L_00d1: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now() 85 L_00d6: stloc.s CS$0$0004 86 L_00d8: ldloca.s CS$0$0004 87 L_00da: call instance int32 [mscorlib]System.DateTime::get_Day() 88 L_00df: stloc.s CS$0$0005 89 L_00e1: ldloca.s CS$0$0005 90 L_00e3: call instance string [mscorlib]System.Int32::ToString() 91 L_00e8: stelem.ref 92 L_00e9: ldloc.s CS$0$0000 93 L_00eb: ldc.i4.5 94 L_00ec: ldstr "\u65e5" 95 L_00f1: stelem.ref 96 L_00f2: ldloc.s CS$0$0000 97 L_00f4: ldc.i4.6 98 L_00f5: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 99 L_00fa: ldstr "EmailTitle" 100 L_00ff: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 101 L_0104: callvirt instance string [mscorlib]System.Object::ToString() 102 L_0109: stelem.ref 103 L_010a: ldloc.s CS$0$0000 104 L_010c: call string [mscorlib]System.String::Concat(string[]) 105 L_0111: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_EmailTitle(string) 106 L_0116: ldloc.1 107 L_0117: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 108 L_011c: ldstr "EmSubject" 109 L_0121: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 110 L_0126: callvirt instance string [mscorlib]System.Object::ToString() 111 L_012b: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_EmSubject(string) 112 L_0130: ldloc.1 113 L_0131: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 114 L_0136: ldstr "SendEmil" 115 L_013b: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 116 L_0140: callvirt instance string [mscorlib]System.Object::ToString() 117 L_0145: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_SendEmilPerson(string) 118 L_014a: ldloc.1 119 L_014b: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 120 L_0150: ldstr "ToEmail" 121 L_0155: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 122 L_015a: callvirt instance string [mscorlib]System.Object::ToString() 123 L_015f: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_ToEmail(string) 124 L_0164: ldloc.1 125 L_0165: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 126 L_016a: ldstr "SendEmil" 127 L_016f: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 128 L_0174: callvirt instance string [mscorlib]System.Object::ToString() 129 L_0179: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_FromEmail(string) 130 L_017e: ldloc.1 131 L_017f: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 132 L_0184: ldstr "SendEmailAcount" 133 L_0189: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 134 L_018e: callvirt instance string [mscorlib]System.Object::ToString() 135 L_0193: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_SendEmailAcount(string) 136 L_0198: ldloc.1 137 L_0199: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 138 L_019e: ldstr "SendEmialPswd" 139 L_01a3: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 140 L_01a8: callvirt instance string [mscorlib]System.Object::ToString() 141 L_01ad: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_SendEmailPsd(string) 142 L_01b2: ldloc.1 143 L_01b3: ldloc.3 144 L_01b4: ldloc.2 145 L_01b5: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::SetEmailAttactment(string, string) 146 L_01ba: ldloc.1 147 L_01bb: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 148 L_01c0: ldstr "SmtpHost" 149 L_01c5: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 150 L_01ca: callvirt instance string [mscorlib]System.Object::ToString() 151 L_01cf: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_SmtpHost(string) 152 L_01d4: ldloc.1 153 L_01d5: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 154 L_01da: ldstr "SmtpServePort" 155 L_01df: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 156 L_01e4: callvirt instance string [mscorlib]System.Object::ToString() 157 L_01e9: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_SmtpServePort(string) 158 L_01ee: ldloc.1 159 L_01ef: call class [System]System.Collections.Specialized.NameValueCollection [System]System.Configuration.ConfigurationSettings::get_AppSettings() 160 L_01f4: ldstr "EmailContent" 161 L_01f9: callvirt instance string [System]System.Collections.Specialized.NameValueCollection::get_Item(string) 162 L_01fe: callvirt instance string [mscorlib]System.Object::ToString() 163 L_0203: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::set_EmailContent(string) 164 L_0208: ldloc.1 165 L_0209: callvirt instance void [GSP.Common]GSP.Common.Utils.EmailUtil::SendEmail() 166 L_020e: ldsfld class [log4net]log4net.ILog ExcelAutoReport.SftxExcelAutoReport::log 167 L_0213: ldstr "\u90ae\u4ef6\u53d1\u9001\u6210\u529f\uff01" 168 L_0218: callvirt instance void [log4net]log4net.ILog::Info(object) 169 L_021d: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now() 170 L_0222: stloc.s dtNow 171 L_0224: ldc.i4.5 172 L_0225: newarr string 173 L_022a: stloc.s CS$0$0006 174 L_022c: ldloc.s CS$0$0006 175 L_022e: ldc.i4.0 176 L_022f: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now() 177 L_0234: stloc.s CS$0$0007 178 L_0236: ldloca.s CS$0$0007 179 L_0238: ldstr "yyyy-MM-dd" 180 L_023d: call instance string [mscorlib]System.DateTime::ToString(string) 181 L_0242: stelem.ref 182 L_0243: ldloc.s CS$0$0006 183 L_0245: ldc.i4.1 184 L_0246: ldstr " " 185 L_024b: stelem.ref 186 L_024c: ldloc.s CS$0$0006 187 L_024e: ldc.i4.2 188 L_024f: call class ExcelAutoReport.SystemConfiguration ExcelAutoReport.SystemConfiguration::GetInstance() 189 L_0254: callvirt instance string ExcelAutoReport.SystemConfiguration::get_GatherHour() 190 L_0259: stelem.ref 191 L_025a: ldloc.s CS$0$0006 192 L_025c: ldc.i4.3 193 L_025d: ldstr ":" 194 L_0262: stelem.ref 195 L_0263: ldloc.s CS$0$0006 196 L_0265: ldc.i4.4 197 L_0266: call class ExcelAutoReport.SystemConfiguration ExcelAutoReport.SystemConfiguration::GetInstance() 198 L_026b: callvirt instance string ExcelAutoReport.SystemConfiguration::get_GatherMinute() 199 L_0270: stelem.ref 200 L_0271: ldloc.s CS$0$0006 201 L_0273: call string [mscorlib]System.String::Concat(string[]) 202 L_0278: call valuetype [mscorlib]System.DateTime [mscorlib]System.Convert::ToDateTime(string) 203 L_027d: stloc.s dtNext 204 L_027f: ldloca.s dtNext 205 L_0281: ldc.r8 1 206 L_028a: call instance valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::AddDays(float64) 207 L_028f: ldloc.s dtNow 208 L_0291: call valuetype [mscorlib]System.TimeSpan [mscorlib]System.DateTime::op_Subtraction(valuetype [mscorlib]System.DateTime, valuetype [mscorlib]System.DateTime) 209 L_0296: call void [mscorlib]System.Threading.Thread::Sleep(valuetype [mscorlib]System.TimeSpan) 210 L_029b: leave L_0000 211 L_02a0: stloc.s exc 212 L_02a2: ldsfld class [log4net]log4net.ILog ExcelAutoReport.SftxExcelAutoReport::log 213 L_02a7: ldloc.s exc 214 L_02a9: callvirt instance string [mscorlib]System.Object::ToString() 215 L_02ae: callvirt instance void [log4net]log4net.ILog::Error(object) 216 L_02b3: ldstr "\u51fd\u6570AutoReportSend \u51fa\u9519\uff0c\u5177\u4f53\u60c5\u51b5\u8bf7\u68c0\u67e5\u65e5\u5fd7" 217 L_02b8: call void [GSP.Common]GSP.Common.SendMessage::MessageSending(string) 218 L_02bd: ldc.i4 0x927c0 219 L_02c2: call void [mscorlib]System.Threading.Thread::Sleep(int32) 220 L_02c7: leave L_0000 221 .try L_0000 to L_02a0 catch [mscorlib]System.Exception handler L_02a0 to L_02cc 222 } 223 224 225 226 227


看来编译的时候,编译器把while(true)转换成了goto结构,以前见过一片文章介绍goto结构在程序开发中的优劣,高德纳也曾为迪杰斯对goto语句的批评而辩护过,看来在开发过程中适当的、少量的使用goto结构也是有利于提高效率的,要不编译器也不会做这样的处理,接下来我试验了下,对for, while结构中对break,continue,编译器会做什么优化处理,下面是我发现的几种情况(只列举下for的代码例子)
public int SummaryArray1(int[] array) { int result = 0; for (int index = 0; index < array.Length; index++) { if (index == 3) break; result += array[index]; } return result; } .NET Reflector 下查看到得代码如下: public int SummaryArray1(int[] array) { int result = 0; for (int index = 0; index < array.Length; index++) { if (index == 3) { return result; } result += array[index]; } return result; }


public double SummarySalary1() { double[] number = { 1200, 1763.4, -15, 3700, 2589, 4366, 3335.8 }; double summaryNum = 0; for (int index = 0; index < 7; index++) { if (number[index] < 0) continue; summaryNum += number[index]; } return summaryNum; } .NET Reflector下查看到的代码如下: public double SummarySalary1() { double[] number = new double[] { 1200.0, 1763.4, -15.0, 3700.0, 2589.0, 4366.0, 3335.8 }; double summaryNum = 0.0; for (int index = 0; index < 7; index++) { if (number[index] >= 0.0) { summaryNum += number[index]; } } return summaryNum; }

如果编译器会做如此处理,我觉得是否可以在代码中也这样处理,替换continue,break呢,希望大家多多讨论,集思广益。
Tags:  gcc编译器 c编译器 java编译器 c语言编译器 编译器

延伸阅读

最新评论

发表评论