代码改变世界

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

2010-12-23 17:39  潇湘隐者  阅读(2367)  评论(17编辑  收藏  举报

在做一个日报自动报表发送项目时,因为项目是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文件时候,发现里面的这段代码变成了下面的样子

 

代码
publicvoid 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呢,希望大家多多讨论,集思广益。