• 奇妙的decimal,或许面试会问到哦~


    这段时间忙的像狗一样,写博客的事情也就耽搁了,继续扯,为什么说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和explicitkeyword,这两个就是所谓的转换操作符,顾名思义,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         }
    复制代码

     

    好了。我想你一切都清楚了,当我们在愉快的写着++,--的时候。殊不知编译器给我们做的太多太多,最后得要感谢一下编译器。

  • 相关阅读:
    【LintCode题集】Q539
    【LintCode题解】Q407
    【LintCode题集】Q6、Q64
    【Java安全】关于Java中常用加密/解密方法的实现
    【MySQL】MySQL5.7的安装与配置
    理解CSS3 max/min-content及fit-content等width值
    Django和MySQL数据库第一次连接时遇到的若干问题及解决办法
    使用Pycharm社区版启动Django的重要补充
    使用Pycharm社区版新建Python3.7的虚拟环境并安装启动Django的完整步骤
    04-图形化编辑器功能不全?
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/6832875.html
Copyright © 2020-2023  润新知