这段时间忙的像狗一样,写博客的事情也就耽搁了,继续扯,为什么说decimal神奇呢,大家都知道decimal是基元类型,但是
这个decimal类型在IL中居然没有相应的IL指令,也就是说CLR根本不认识decimal,全是编译器这一层在糊弄我们。
话不多说,看下最simple的例子,(加了点注释方便理解)
1staticvoidMain(string[] args)2{3//居然调用了有参构造函数4decimald =1;56//直接将常量10推送到计算堆栈,然后将10放入局部变量索引为1的位置,也就是i7inti =10;89//居然调用了隐式转换操作符,IL中就是调用相应的方法10d =i;1112//居然调用了显式转换操作符,IL中就是调用相应的方法13i = (int)d;14}
从IL中可以看到,对decimal的所有操作最后玩的都是方法,对编译器上层的我们而言却一无所知,那么下一个问题来了,这些
都是怎么做到的呢?
一:decimal源代码
当我们对decimal的实现充满好奇心的时候,最满足的方式的就是看源代码了,大家应该都有对新鲜事物的好奇心,不管看不看
得懂都得装X看。
1:implicit/explicit 操作符
从下面的IL中我们看到了这些乱七八槽的操作符,可能我们用的比较少或者有些人都没看过,不过终有它的用武之地。
结合上面的IL代码,我们发现了implicit和explicit关键字,这两个就是所谓的转换操作符,顾名思义,implicit就是所谓的隐式转换
操作符,explicit是显式转换了,再结合上面的IL代码,我们会发现给我们最终生成的是op_Implicit 和 op_Explicit方法。
可能有些人看不明白了,那我就举个例子吧。
1publicclassPRogram2{3staticvoidMain(string[] args)4{5//这里就是语法糖,c=10 最终调用的就是:隐式转换调用6Complex c =10;78//语法糖,(int)最终调用的是:显式转换调用9intj = (int)c;10}11}1213publicstructComplex14{15publicComplex(intnum) { }1617///<summary>18///隐式转换调用的方法19///</summary>20///<param name="value"></param>21///<returns></returns>22publicstaticimplicitOperatorComplex(intvalue)23{24returnnewComplex(value);25}2627///<summary>28///强制转换调用的方法29///</summary>30///<param name="value"></param>31///<returns></returns>32publicstaticexplicitoperatorint(Complex value)33{34returnConvert.ToInt32(value);35}36}
从我的sample和IL中看,我想你应该清楚了,为了方便我们编码效率以及更好的让人理解,C#提供了这么个好玩的语法糖,清晰明了。
2:op_*** 重载操作符
既然是基元类型就避免不了大量的算术运算和比较元算,那这些decimal又是如何做到的?还是继续在源代码里面找找。
从源代码里面可以看到,原来C#用operator重载运算符对我们这个++,--,!=,<= 进行了重载,和转换运算符一样,最终
在IL层也是转换为各种方法。
还是看个例子:
1staticvoidMain(string[] args)2{3decimali =10;45decimalj =12;67varr1 = i >j;89varr2 = i ==j;10}
好了,我想你一切都清楚了,当我们在愉快的写着++,--的时候,殊不知编译器给我们做的太多太多,最后得要感谢一下编译器。