C#对switch语句的优化

来源:互联网 发布:网络声优招聘 编辑:程序博客网 时间:2024/06/10 08:38

 
1     一直以为C#中的switch语句在处理字符串时是用if语句来构造的,因为.net的IL中的switch也逃不脱C的宿命--只能
2    处理数字,而实际上C#编译器对switch语句对字符串的处理却让人汗啊.
3     首先编译一下下面的代码:
4    using System;
5    class EntryPoint
6    {
7     private static void Main()
8     {
9      Console.WriteLine("请输入序号:a,b,c,d,e,f");
10      string szInput = Console.ReadLine();
11      switch (szInput)
12      {
13       case "a":
14        Console.WriteLine("你输入的是:a"); 
15        break;
16   
17       case "b":
18        Console.WriteLine("你输入的是:b"); 
19        break;
20   
21       case "c":
22        Console.WriteLine("你输入的是:c"); 
23        break;   
24   
25       case "d":
26        Console.WriteLine("你输入的是:a"); 
27        break;
28   
29       case "e":
30        Console.WriteLine("你输入的是:e"); 
31        break;
32   
33       case "f":
34        Console.WriteLine("你输入的是:f"); 
35        break;
36   
37       default :
38        Console.WriteLine("你输入的是:{0}",szInput);
39        break;
40      }
41      Console.Read();
42     }
43    }
44   
45    再用Reflector反编译上面源代码编译出来的程序,下面是反编译出来的代码
46    private static void Main()
47    {
48          Console.WriteLine("/u8bf7/u8f93/u5165/u5e8f/u53f7:a,b,c,d,e,f");
49          string text1 = Console.ReadLine();
50          string text2 = text1;
51          if (text2 != null)
52          {
53                int num2;
54                if (<PrivateImplementationDetails>{FEB70444-128D-453C-8E6F-C839E1DC2F51}.$method0x6000001-1 == null)
55                {
56                      Dictionary<string, int> dictionary1 = new Dictionary<string, int>(6);
57                      dictionary1.Add("a", 0);
58                      dictionary1.Add("b", 1);
59                      dictionary1.Add("c", 2);
60                      dictionary1.Add("d", 3);
61                      dictionary1.Add("e", 4);
62                      dictionary1.Add("f", 5);
63                      <PrivateImplementationDetails>{FEB70444-128D-453C-8E6F-C839E1DC2F51}.$method0x6000001-1 = dictionary1;
64                }
65                if (<PrivateImplementationDetails>{FEB70444-128D-453C-8E6F-C839E1DC2F51}.$method0x6000001-1.TryGetValue(text2, out num2))
66                {
67                      switch (num2)
68                      {
69                            case 0:
70                                  Console.WriteLine("/u4f60/u8f93/u5165/u7684/u662f:a");
71                                  goto Label_0105;
72   
73                            case 1:
74                                  Console.WriteLine("/u4f60/u8f93/u5165/u7684/u662f:b");
75                                  goto Label_0105;
76   
77                            case 2:
78                                  Console.WriteLine("/u4f60/u8f93/u5165/u7684/u662f:c");
79                                  goto Label_0105;
80   
81                            case 3:
82                                  Console.WriteLine("/u4f60/u8f93/u5165/u7684/u662f:a");
83                                  goto Label_0105;
84   
85                            case 4:
86                                  Console.WriteLine("/u4f60/u8f93/u5165/u7684/u662f:e");
87                                  goto Label_0105;
88   
89                            case 5:
90                                  Console.WriteLine("/u4f60/u8f93/u5165/u7684/u662f:f");
91                                  goto Label_0105;
92                      }
93                }
94          }
95          Console.WriteLine("/u4f60/u8f93/u5165/u7684/u662f:{0}", text1);
96    Label_0105:
97          Console.Read();
98    }
99   
100      可以看到C#编译器把所有case标签里的字符串按顺序存储到泛型的字典$method0x6000001-1中(键是标签值,值是标签序号
101    ).而$method0x6000001-1则是<PrivateImplementationDetails>{FEB70444-128D-453C-8E6F-C839E1DC2F51}类中的一个静态
102    字段.下面是<PrivateImplementationDetails>{FEB70444-128D-453C-8E6F-C839E1DC2F51}的代码
103    [CompilerGenerated]
104    internal class <PrivateImplementationDetails>{FEB70444-128D-453C-8E6F-C839E1DC2F51}
105    {
106          // Fields
107          internal static Dictionary<string, int> $method0x6000001-1;
108    }
109   
110      用过VC的人可能知道在VC中当swith语句中的标签大于一定的数量时VC编译器会建立一个散列表来提升case标签的查找性能
111    .呵呵!没想到这个思想在如今的C#编译器中也得到了应用,真让人喜出望外啊!
112      或许有人会认为以上的代码多了一个字典字段的初始化而switch中的标签也并没有削减可能反而会影响了性能.这些不必担
113    忧因为:
114    1,由于Dictionary的存储结构是散列结构,所以它查找起起数据来;
115    2,switch语句在IL中是直接支持的,所以不用过滤;
116    3,Dictionary字段是一个静态字段,只须初始化一次;
117    4,俺们挖空心思的优化自己的代码,还不如编译器的优化好(失败的打击).
118   
119      但是,正如VC编译器一样C#编译器并不会对所有的字符串的swith语句都用字典来存储,而是当case标签的数量在>=6个时才
120    用字典来提升查找性能.
121   
122    注意:以上的代码如果用C#1.0编译将会有所差异其中用来存储标签中的字符串的对象不是Dictionary而是HashTable.


本文来自CSDN博客,出处:http://blog.csdn.net/gu_fan/archive/2006/06/22/821049.aspx

原创粉丝点击