编写高质量代码的30条黄金守则(首选隐式类型转换)
编写高质量代码的30条黄金守则-Day01(首选隐式类型转换),本文由比特飞原创发布,转载务必在文章开头附带链接:https://www.byteflying.com/archives/6455
该系列文章由比特飞原创发布,计划用三个月时间写完全30篇文章,为大家提供编写高质量代码的一般准则。
1、概述
隐式类型转换是微软为了C#支持匿名类型而加入的,使用var通常可以使代码的可读性更强,甚至是帮我们解决一些严重的性能问题。为了清楚的明白var的作用机制,我们首先来看看编译器为var做了哪些工作?
2、编译器为var关键字做了什么?
首先var为语法糖,编译器在编译时根据右值推断出表达式类型,再由编译器将推断出的表达式类型写入到IL中,所以如下2段代码在IL中完全一致。
编译期间,编译器根据右值“SomeString”,可以推断出这个表达式(右值)的类型为string类型,于是将var替换为string,再将它写到IL中,于是以上两段初始化foo的代码结果完全一致。
stringfoo="SomeString"; varfoo="SomeString";
我们再来看一下两段代码的IL:
本文示例的源代码
DnSpy的反编译结果
Microsoft技术支持文档中ldstr的解释
注意:string也是语法糖,编译时,string被替换为System.String写进IL。
于是我们得到了一个重要的结论:
var为语法糖,在编译期间就已经被编译器所决定,开发人员无法为编译器决定类型。
隐式类型转换为上述代码带来了良好的可读性,任何一名开发人员都会知道第2行代码的var的类型,它让我们更加的关注代码片段中我们所需要关注的部分,而不是把重点放在它的类型上。因为大多数时候,这都是没有意义的。
3、隐式类型转换所带来的良好可读性
为了明白良好可读性的问题,我们先来看一个代码片段:
varfoo=newSomeType();
以上代码清晰明了,对于维护代码的人来说,它没有增加任何的理解成本,foo的类型就是SomeType类型。很多优秀开源项目中的大量被使用的工厂模式,也提供了类似的方法,如下代码片段:
varhuaWei=PhoneFactory.CreatePhone();
一个简单的静态工厂类PhoneFactory,公开了CreatePhone方法,阅读这段代码的开发人员,在几乎没有增加理解成本的情况下,很清楚的知道huaWei代表手机工厂类所生产的一个手机对象。但是下面的代码,情况可能就稍有不同了:
varresult=someObject.DoSomething(someParameter);
你无法轻松的知道result的类型和它所表达的意义,事实上,它的不良好的可读性,表现在以下几个方面:
1、在此处,result这个变量名并不是最好的选择;
2、someObject的含义不明;
3、DoSomething含糊不清;
4、无法明确的知道someParameter代码什么。
如果换成以下代码,情况会好很多:
varmostPopularPhone=someObject.DoSomething(someParameter);
情况有所好转,意思也更清楚。结合语义上下文,var的类型不言自明。但是在这种情况下,我依然建议大家将代码改为以下形式:
PhonemostPopularPhone=someObject.DoSomething(someParameter);
这被我写在之前所在公司的开发手册上,我相信我的经验一定是正确的。
让我们再来看一个新的示例:
varscore=GetSomeNumber(); varrate=score/100;
rate的类型由变量score决定,然后开发者无法一眼看出score的类型,所以这是一个不良好的可读性的代码片段,我们应该改为:
varscore=GetSomeNumber(); doublerate=score/100;
怎么样,是不是看到这样的代码,心里舒服多了?因为你的理解成本更低了,心情舒畅了,一下子搬砖都能搬到5楼了。
于是,我们有了两点总结:
1、当含义明确,在代码上下文较为清楚时(简单的变量定义或工厂方法),建议优先使用var;
2、在其它复杂情况下,尽量直接写出var的类型。
隐式类型转换所带来的绝非仅仅是良好的可读性,它有时可能会帮我们消除一些难以发现的Bug,这又是怎么回事呢?
4、隐式类型转换帮我们解决严重的性能问题
人自以为自己是世界上最聪明的生物,事实上并非如此,有时候,编译器比我们聪明得多,也可靠得多。
我们看看以下两个代码片段:
publicIEnumerableGetPhoneStartsWith1(stringprefix){ IEnumerable phones= fromrindb.Phones selectr.PhoneName; varresult=phones.Where(r=>r.StartsWith(prefix)); returnresult; } publicIEnumerable GetPhoneStartsWith2(stringprefix){ varphones= fromrindb.Phones selectr.PhoneName; varresult=phones.Where(r=>r.StartsWith(prefix)); returnresult; }
以上两段代码有何不同?GetPhoneStartsWith1方法中的phones原先的返回类型应当为IQueryable
于是GetPhoneStartsWith1方法将数据库中的可能的所有数据全部取回本地,再由varresult=phones.Where(r=>r.StartsWith(prefix));执行本地过滤,消耗了太多网络资源,并且使用了.Net的数据过滤机制。
GetPhoneStartsWith2方法则不然,phones的类型被编译器推断为IQueryable
5、总结
- 当含义明确,在代码上下文较为清楚时(简单的变量定义或工厂方法),建议优先使用var;
- 在其它复杂情况下,尽量直接写出var的类型;
- 尽可能地相信编译器,大多数时候,它比我们优秀得多。
开发人员应牢记以上开发守则,否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你。
该系列文章由比特飞原创发布,计划用三个月时间写完全30篇文章,为大家提供编写高质量代码的一般准则。
总结
到此这篇关于编写高质量代码的30条黄金守则(首选隐式类型转换)的文章就介绍到这了,更多相关编写高质量代码的30条黄金守则内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。