C#_Switch語句的內部實現


Switch的C#內部實現

https://www.cnblogs.com/Interkey/p/3730432.html

在IL匯編語言中的Switch指令 -- 按照標號來進行跳轉(和goto語句中的標號相同)
  執行IL中Switch指令時,從運算棧頂彈出一個無符號整數,然后跳轉到整數對應的標號位置繼續執行
  如果整數值沒有對應的標號,則忽略switch指令,調到switch指令之后的一條指令開始執行。

詳細分析:

  -- 結論 (實驗過程見原網頁)  

1. 整數參數的Switch語句  

1a. 連續的整數
    c#的switch的case語句對應IL的switch指令中的case子句

1b. 不連續的但是相近的整數
    c#的switch的case語句對應IL的switch指令中的case子句,
    但是對於case指令之間的"縫隙"整數,會自動跳轉default子句的地址

1c. 很不連續的整數
    如果按1b的思路,縫隙很大的話,IL中switch指令會憑空增加很多指向default子句指向地址的case子句
    編譯器不使用switch指令,而是使用了beq指令 -- 取值若相等則跳轉到目標位置,否則繼續下一個取值

2. 枚舉類型的Switch語句
  與對待整數沒有差別,因為枚舉值就是按照整數對待的;如果枚舉成員的取值不連續,則對應1b或1c

3. string類型的Switch語句

3a. case子句數量<=4時
  string是引用類型參數
  同樣在IL中沒有使用switch指令
    如果參數為null的話,則執行流程直接跳轉到case null的指令塊中
    否則,比較參數與case語句對應string的相等性(==),若相等,則跳轉到對應的地址后,跳出switch
  -- 這就相當於被編譯成了一連串的if語句
    那么,當case子句過多時,豈不是會導致程序變慢?

3b. case子句數量>4時
  如果不是null的話,則會實例化一個字典泛型類 System.Collections.Generic.Dictionary`2<string,int32>
  將分別出現在case子句中的string作為key插入到字典中,每個key的value分別對應從0開始的整數(switch子句的序號)
  調用字典的TryGetValue()嘗試從字典中找到string參數所對應的字典元素
  如果在字典中沒找到,則跳轉到default子句對應的位置
  如果找到了,這里出現了switch指令,根據從字典中取到的value整數值,進行switch子句的跳轉
    switch之后的一條指令則為一個無條件跳轉,直接跳轉到default子句
    這里是當switch指令在棧頂取到的整數值比switch指令中跳轉地址數量要大時,忽略switch直接執行之后的指令

總結:

3b情況下,由於Dictionary<TKey,TValue>類型通過key來取值的時間復雜度接近於O(1) -- 有助於提高效率

為了微乎其微的效率提升
  1. 盡量在switch中使用連續的取值
  2. 如果取值不連續,則使用盡量少的case子句,並將會出現頻率高的case放在前面(與if...else if...else類似)
  3. 如果使用了大量if語句來判斷一個字符串對象是否具有某值,改用Switch
  4. 有其他引用類型對象想要使用switch判斷但又不能使用時,可以按照3b的思路自己實現。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM