神奇的decimal,也许面试会问到哦~

神奇的decimal,也许面试会问到哦~,第1张

概述 这段时间忙的像狗一样,写博客的事情也就耽搁了,继续扯,为什么说decimal神奇呢,大家都知道decimal是基元类型,但是这个decimal类型在IL中居然没有相应的IL指令,也就是说CLR根本不认识decimal,全是编译器这一层在糊弄我们。     话不多说,看下最simple的例子,(加了点注释方便理解)1 static void Main(string[] args)2 {3 //居然调用了有参构造函数4 decimal d = 1;56 //直接将常量10推送到计算堆栈,然后将10放入局部变量索引为1的位置,也就是i7 int i = 10;89 //居然调用了隐式转换 *** 作符,IL中就是调用相应的方法10 d = i;1112 //居然调用了显式转换 *** 作符,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 Program2 {3 static void Main(string[] args)4 {5 //这里就是语法糖,c=10 最终调用的就是:隐式转换调用6 Complex c = 10;78 //语法糖,(int)最终调用的是:显式转换调用9 int j = (int)c;10 }11 }1213 public struct Complex14 {15 public Complex(int num) { }1617 /// <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 }2627 /// <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;45 decimal j = 12;67 var r1 = i > j;89 var r2 = i == j;10 } 好了,我想你一切都清楚了,当我们在愉快的写着++,--的时候,殊不知编译器给我们做的太多太多,最后得要感谢一下编译器。 

  这段时间忙的像狗一样,写博客的事情也就耽搁了,继续扯,为什么说decimal神奇呢,大家都知道decimal是基元类型,但是

这个decimal类型在IL中居然没有相应的IL指令,也就是说CLR根本不认识decimal,全是编译器这一层在糊弄我们。

     话不多说,看下最simple的例子,(加了点注释方便理解)

Main( d = i = d = i = ( }

从IL中可以看到,对decimal的所有 *** 作最后玩的都是方法,对编译器上层的我们而言却一无所知,那么下一个问题来了,这些

都是怎么做到的呢?

一:decimal源代码

当我们对decimal的实现充满好奇心的时候,最满足的方式的就是看源代码了,大家应该都有对新鲜事物的好奇心,不管看不看

得懂都得装X看。

1:implicit/explicit *** 作符

    从下面的IL中我们看到了这些乱七八槽的 *** 作符,可能我们用的比较少或者有些人都没看过,不过终有它的用武之地。

结合上面的IL代码,我们发现了implicit和explicit关键字,这两个就是所谓的转换 *** 作符,顾名思义,implicit就是所谓的隐式转换

*** 作符,explicit是显式转换了,再结合上面的IL代码,我们会发现给我们最终生成的是op_Implicit 和 op_Explicit方法。

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

Main( Complex c = j = ( Complex( Complex( }

从我的sample和IL中看,我想你应该清楚了,为了方便我们编码效率以及更好的让人理解,C#提供了这么个好玩的语法糖,清晰明了。

2:op_*** 重载 *** 作符

    既然是基元类型就避免不了大量的算术运算和比较元算,那这些decimal又是如何做到的?还是继续在源代码里面找找。

   从源代码里面可以看到,原来C#用operator重载运算符对我们这个++,--,!=,<= 进行了重载,和转换运算符一样,最终

在IL层也是转换为各种方法。

   还是看个例子:

Main( i = j = r1 = i > r2 = i == }

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

总结

以上是内存溢出为你收集整理的神奇的decimal,也许面试会问到哦~全部内容,希望文章能够帮你解决神奇的decimal,也许面试会问到哦~所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1264082.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存