编写高质量代码的30条黄金守则-Day 01(首选隐式类型转换),本文由比特飞原创发布,转载务必在文章开头附带链接:https://www.byteflying.com/archives/6455

该系列文章由比特飞原创发布,计划用三个月时间写完全30篇文章,为大家提供编写高质量代码的一般准则。

1、概述

隐式类型转换是微软为了 C# 支持匿名类型而加入的,使用 var 通常可以使代码的可读性更强,甚至是帮我们解决一些严重的性能问题。为了清楚的明白 var 的作用机制,我们首先来看看编译器为 var 做了哪些工作?

2、编译器为var关键字做了什么?

首先 var 为语法糖,编译器在编译时根据右值推断出表达式类型,再由编译器将推断出的表达式类型写入到 IL 中,所以如下2段代码在 IL 中完全一致。

string foo = "SomeString";

var foo = "SomeString";

编译期间,编译器根据右值 “SomeString” ,可以推断出这个表达式(右值)的类型为 string 类型,于是将 var 替换为 string ,再将它写到IL中,于是以上两段初始化 foo 的代码结果完全一致。

我们再来看一下两段代码的IL:

编写高质量代码的30条黄金守则-Day 01(首选隐式类型转换)

本文示例的源代码

DnSpy 的反编译结果

编写高质量代码的30条黄金守则-Day 01(首选隐式类型转换)

Microsoft 技术支持文档中 ldstr 的解释

注意:string 也是语法糖,编译时,string 被替换为 System.String 写进IL。

于是我们得到了一个重要的结论:

var 为语法糖,在编译期间就已经被编译器所决定,开发人员无法为编译器决定类型。

隐式类型转换为上述代码带来了良好的可读性,任何一名开发人员都会知道第2行代码的 var 的类型,它让我们更加的关注代码片段中我们所需要关注的部分,而不是把重点放在它的类型上。因为大多数时候,这都是没有意义的。

3、隐式类型转换所带来的良好可读性

为了明白良好可读性的问题,我们先来看一个代码片段:

var foo = new SomeType();

以上代码清晰明了,对于维护代码的人来说,它没有增加任何的理解成本,foo 的类型就是 SomeType 类型。很多优秀开源项目中的大量被使用的工厂模式,也提供了类似的方法,如下代码片段:

var huaWei = PhoneFactory.CreatePhone();

一个简单的静态工厂类 PhoneFactory ,公开了 CreatePhone 方法,阅读这段代码的开发人员,在几乎没有增加理解成本的情况下,很清楚的知道 huaWei 代表手机工厂类所生产的一个手机对象。但是下面的代码,情况可能就稍有不同了:

var result = someObject.DoSomething(someParameter);

你无法轻松的知道 result 的类型和它所表达的意义,事实上,它的不良好的可读性,表现在以下几个方面:

1、在此处,result 这个变量名并不是最好的选择;

2、someObject 的含义不明;

3、DoSomething 含糊不清;

4、无法明确的知道 someParameter 代码什么。

如果换成以下代码,情况会好很多:

var mostPopularPhone = someObject.DoSomething(someParameter);

情况有所好转,意思也更清楚。结合语义上下文,var 的类型不言自明。但是在这种情况下,我依然建议大家将代码改为以下形式:

Phone mostPopularPhone = someObject.DoSomething(someParameter);

这被我写在之前所在公司的开发手册上,我相信我的经验一定是正确的。

让我们再来看一个新的示例:

var score = GetSomeNumber();

var rate = score / 100;

rate 的类型由变量 score 决定,然后开发者无法一眼看出 score 的类型,所以这是一个不良好的可读性的代码片段,我们应该改为:

var score = GetSomeNumber();

double rate = score / 100;

怎么样,是不是看到这样的代码,心里舒服多了?因为你的理解成本更低了,心情舒畅了,一下子搬砖都能搬到5楼了。

于是,我们有了两点总结:

1、当含义明确,在代码上下文较为清楚时(简单的变量定义或工厂方法),建议优先使用 var;

2、在其它复杂情况下,尽量直接写出 var 的类型。

隐式类型转换所带来的绝非仅仅是良好的可读性,它有时可能会帮我们消除一些难以发现的Bug,这又是怎么回事呢?

4、隐式类型转换帮我们解决严重的性能问题

人自以为自己是世界上最聪明的生物,事实上并非如此,有时候,编译器比我们聪明得多,也可靠得多。

我们看看以下两个代码片段:

public IEnumerable GetPhoneStartsWith1(string prefix) {

IEnumerable phones =

from r in db.Phones

select r.PhoneName;

var result = phones.Where(r => r.StartsWith(prefix));
return result;

}

public IEnumerable GetPhoneStartsWith2(string prefix) {

var phones =

from r in db.Phones

select r.PhoneName;

var result = phones.Where(r => r.StartsWith(prefix));
return result;

}

以上两段代码有何不同?GetPhoneStartsWith1 方法中的 phones 原先的返回类型应当为 IQueryable,但在这里被显式声明的 phones 的 IEnumerable 给强制转换了,熟悉 EF 的朋友们一定知道,IQueryable 为延迟加载,本身并不会立刻查询数据库,事实上它只生成了一个表达式树,在最终需要使用数据的时候才会真正执行查询动作。

于是 GetPhoneStartsWith1 方法将数据库中的可能的所有数据全部取回本地,再由 var result = phones.Where(r => r.StartsWith(prefix)); 执行本地过滤,消耗了太多网络资源,并且使用了 .Net 的数据过滤机制。

GetPhoneStartsWith2 方法则不然,phones 的类型被编译器推断为 IQueryable ,并不会因此执行查询操作,真正的查询动作由 var result = phones.Where(r => r.StartsWith(prefix)); 执行,也就是说,它的数据过滤动作由数据库引擎负责运算,最终只将符合条件的数据发送回本地,既节省了网络传递成本,又节省了运算成本,岂不是一举两得?

5、总结

当含义明确,在代码上下文较为清楚时(简单的变量定义或工厂方法),建议优先使用 var;

在其它复杂情况下,尽量直接写出 var 的类型;

尽可能地相信编译器,大多数时候,它比我们优秀得多。

开发人员应牢记以上开发守则,否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你。

该系列文章由比特飞原创发布,计划用三个月时间写完全30篇文章,为大家提供编写高质量代码的一般准则。

本文由 比特飞 原创发布,欢迎大家踊跃转载。

转载请注明本文地址:https://www.byteflying.com/archives/6455。

编写高质量代码的30条黄金守则-Day 01(首选隐式类型转换)的更多相关文章

  1. 编写高质量代码的50条黄金守则-Day 02(首选readonly而不是const)

    编写高质量代码的50条黄金守则-Day 02(首选readonly而不是const),本文由比特飞原创发布,转载务必在文章开头附带链接:https://www.byteflying.com/archi ...

  2. 编写高质量代码改善C#程序的157个建议——建议30:使用LINQ取代集合中的比较器和迭代器

    建议30:使用LINQ取代集合中的比较器和迭代器 LINQ提供了类似于SQL的语法来实现遍历.筛选与投影集合的功能. static void Main(string[] args) { List< ...

  3. (第一章)改善JavaScript,编写高质量代码。

    根据<编写高质量代码改善JavaScript程序的188个建议>这本书,来记录我目前所了解的建议方式. 建议1:警惕Unicode乱码 根据ECMA标准规定JavaScript语言可以使用 ...

  4. Github即将破百万的PDF:编写高质量代码改善JAVA程序的151个建议

    在通往"Java技术殿堂"的路上,本书将为你指点迷津!内容全部由Java编码的最佳 实践组成,从语法.程序设计和架构.工具和框架.编码风格和编程思想等五大方面,对 Java程序员遇 ...

  5. 编写高质量代码改善C#程序的157个建议——导航开篇

    前言 由于最近工作重心的转移,原来和几个同事一起开发的项目也已经上线了,而新项目就是在现有的项目基础上进行优化延伸扩展.打个比方,现在已经上线的项目行政案件的Web管理网站(代码还没那么多相比较即将要 ...

  6. 《编写高质量代码:改善Python程序的91个建议》读后感

    编写高质量代码:改善Python程序的91个建议  http://book.douban.com/subject/25910544/ 1.(建议16)is 用于判断两个对象的id是否相等,==才是判断 ...

  7. 编写高质量代码:改善Java程序的151个建议(第二章:基本类型)

    编写高质量代码:改善Java程序的151个建议(第二章:基本类型) 目录 建议21:用偶判断,不用奇判断 建议22:用整数类型处理货币 建议23:不要让类型默默转换 建议24:边界还是边界 建议25: ...

  8. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  9. 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本

    建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...

随机推荐

  1. Ethical Hacking - GAINING ACCESS(15)

    CLIENT SIDE ATTACKS Social Engineering Gather info about the user(s). Build a strategy based on the ...

  2. OSCP Learning Notes - Buffer Overflows(5)

    Generating Shellcode & Gaining Root 1.Generate the shellcode on Kali Linux. LHOST is the IP of K ...

  3. echarts 实战 : 图表竖着或横着是怎样判定的?

    这个问题比较简单. echarts 的图表默认是竖着的. 只要 xAxis 和 yAxis 互换,竖着的图就变成了横着的图了. 所以我们可以可以写一个xy轴互换的方法. reverseXYAxis = ...

  4. scratch编程——画笔模块画各种同心图案

    我们今天是要用画笔来画出不同的同心图案,在画之前,我们先来了解一下画笔模块: 1.画笔模块的用法 画笔模块的用法就是在舞台上留下不同颜色粗细的线条,它的默认是情况是抬笔,我们在使用的时候要让角色移动到 ...

  5. C++语法小记---函数重载

    函数重载 函数重载的本质是对已有功能的扩展 构成重载的三大条件 函数名相同 参数列表不通(与返回值无关) 重载函数的作用域相同 成员函数之间可以重载,成员函数和静态成员函数之间可以构成重载,全局函数之 ...

  6. 切换npm源的几种方法

    我们在使用官方提供的npm源安装各种依赖包的时候,下载速度会很慢,通常需要更换npm源. 我们可以在终端中输入命令 npm config list 来查看 npm 源地址,默认地址为 metrics- ...

  7. 题解 洛谷 P3710 【方方方的数据结构】

    因为有撤销操作,所以修改操作可能会只会存在一段时间,因此把时间看作一维,被修改的序列看作一维. 可以把操作都离线下来,对于每个修改操作,就是在二维平面上对一个矩形进行修改,询问操作,就是查询单点权值. ...

  8. vue学习(十七) 使用自定义指令 使文本框获得鼠标焦点

    需求:当我们进入某个页面,页面中的第一个input会自动获得焦点 光标闪烁,代表可输入 <div id="app"> //v-focus 是自定义的 <input ...

  9. spring notes

    ************************ nexus is a tool of warehouse managementfirst nexus search local warehous ,i ...

  10. Sts 授权直传阿里云 OSS-.net core实现

    前言 磁盘怎么又满了?赶紧 快 打电话给运维扩容扩容扩容!这个问题已经是我入职新公司两个月来,第 3 次听到了.经过一通了解,事情原来是这样的.虽然我们使用了阿里云的 OSS 对象存储服务,但是为了不 ...