文章出處

 

  這段時間忙的像狗一樣,寫博客的事情也就耽擱了,繼續扯,為什么說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         }

 

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

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()