神奇的decimal,也許面試會問到哦~

一線碼農發表於2014-09-23

 

  這段時間忙的像狗一樣,寫部落格的事情也就耽擱了,繼續扯,為什麼說decimal神奇呢,大家都知道decimal是基元型別,但是

這個decimal型別在IL中居然沒有相應的IL指令,也就是說CLR根本不認識decimal,全是編譯器這一層在糊弄我們。

     話不多說,看下最simple的例子,(加了點註釋方便理解)

 1         static void Main(string[] args)
 2         {
 3             //居然呼叫了有參建構函式
 4             decimal d = 1;
 5 
 6             //直接將常量10推送到計算堆疊,然後將10放入區域性變數索引為1的位置,也就是i
 7             int i = 10;
 8 
 9             //居然呼叫了隱式轉換操作符,IL中就是呼叫相應的方法
10             d = i;
11 
12             //居然呼叫了顯式轉換操作符,IL中就是呼叫相應的方法
13             i = (int)d;
14         }

 

從IL中可以看到,對decimal的所有操作最後玩的都是方法,對編譯器上層的我們而言卻一無所知,那麼下一個問題來了,這些

都是怎麼做到的呢?

 

一:decimal原始碼

當我們對decimal的實現充滿好奇心的時候,最滿足的方式的就是看原始碼了,大家應該都有對新鮮事物的好奇心,不管看不看

得懂都得裝X看。

1:implicit/explicit 操作符

    從下面的IL中我們看到了這些亂七八槽的操作符,可能我們用的比較少或者有些人都沒看過,不過終有它的用武之地。

 

結合上面的IL程式碼,我們發現了implicit和explicit關鍵字,這兩個就是所謂的轉換操作符,顧名思義,implicit就是所謂的隱式轉換

操作符,explicit是顯式轉換了,再結合上面的IL程式碼,我們會發現給我們最終生成的是op_Implicit 和 op_Explicit方法。

可能有些人看不明白了,那我就舉個例子吧。

 1     public class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //這裡就是語法糖,c=10 最終呼叫的就是:隱式轉換呼叫
 6             Complex c = 10;
 7 
 8             //語法糖,(int)最終呼叫的是:顯式轉換呼叫
 9             int j = (int)c;
10         }
11     }
12 
13     public struct Complex
14     {
15         public Complex(int num) { }
16 
17         /// <summary>
18         /// 隱式轉換呼叫的方法
19         /// </summary>
20         /// <param name="value"></param>
21         /// <returns></returns>
22         public static implicit operator Complex(int value)
23         {
24             return new Complex(value);
25         }
26 
27         /// <summary>
28         /// 強制轉換呼叫的方法
29         /// </summary>
30         /// <param name="value"></param>
31         /// <returns></returns>
32         public static explicit operator int(Complex value)
33         {
34             return Convert.ToInt32(value);
35         }
36     }

從我的sample和IL中看,我想你應該清楚了,為了方便我們編碼效率以及更好的讓人理解,C#提供了這麼個好玩的語法糖,清晰明瞭。

 

2:op_*** 過載操作符

    既然是基元型別就避免不了大量的算術運算和比較元算,那這些decimal又是如何做到的?還是繼續在原始碼裡面找找。

 

   從原始碼裡面可以看到,原來C#用operator過載運算子對我們這個++,--,!=,<= 進行了過載,和轉換運算子一樣,最終

在IL層也是轉換為各種方法。

   還是看個例子:

 1         static void Main(string[] args)
 2         {
 3             decimal i = 10;
 4 
 5             decimal j = 12;
 6 
 7             var r1 = i > j;
 8 
 9             var r2 = i == j;
10         }

 

好了,我想你一切都清楚了,當我們在愉快的寫著++,--的時候,殊不知編譯器給我們做的太多太多,最後得要感謝一下編譯器。

 

相關文章