该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 01(首选隐式类型转换) | .Net中文网

编写高质量代码的50条黄金守则-Day 01(首选隐式类型转换),本文由比特飞原创发布,转载务必在文章开头附带链接:编写高质量代码的50条黄金守则-Day 01(首选隐式类型转换) | .Net中文网

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

1、概述

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

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

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

string foo = "SomeString";var foo = "SomeString";

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

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

本文示例的源代码

DnSpy 的反编译结果

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<string> GetPhoneStartsWith1(string prefix) {IEnumerable<string> phones =from r in db.Phonesselect r.PhoneName;var result = phones.Where(r => r.StartsWith(prefix));return result;
}
public IEnumerable<string> GetPhoneStartsWith2(string prefix) {var phones =from r in db.Phonesselect r.PhoneName;var result = phones.Where(r => r.StartsWith(prefix));return result;
}

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

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

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

5、总结

  1. 当含义明确,在代码上下文较为清楚时(简单的变量定义或工厂方法),建议优先使用 var;
  2. 在其它复杂情况下,尽量直接写出 var 的类型;
  3. 尽可能地相信编译器,大多数时候,它比我们优秀得多。

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

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

该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 01(首选隐式类型转换) | .Net中文网

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

  1. 编写高质量代码的50条黄金守则-Day 04(首选字符串插值)

    该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 04(首选字符串插值) | .Net中文网. 编写高质量代码的50条黄金守则-Day 04(首选字符串插值),本文由比 ...

  2. 编写高质量代码的50条黄金守则-Day 03(首选is或as而不是强制类型转换)

    该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 03(首选is或as而不是强制类型转换) | .Net中文网. 编写高质量代码的50条黄金守则-Day 03(首选is ...

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

    该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则-Day 02(首选readonly而不是const) | .Net中文网. 编写高质量代码的50条黄金守则-Day 02(首选 ...

  4. 编写高质量代码的50条黄金守则

    该文章由本人原创发布,最新版本现已迁移至:编写高质量代码的50条黄金守则 | .Net中文网. 概述 该系列文章由比特飞原创发布,计划用半年时间写完全50篇文章,为大家提供编写高质量代码的一般准则. ...

  5. 编写高质量代码改善C#程序的157个建议——建议50:在Dispose模式中应区别对待托管资源和非托管资源...

    建议50:在Dispose模式中应区别对待托管资源和非托管资源 真正资源释放代码的那个虚方法是带一个bool参数的,带这个参数,是因为我们在资源释放时要区别对待托管资源和非托管资源. 提供给调用者调用 ...

  6. 读书笔记:编写高质量代码--web前端开发修炼之道(二:5章)

    读书笔记:编写高质量代码--web前端开发修炼之道 这本书看得断断续续,不连贯,笔记也是有些马虎了,想了解这本书内容的童鞋可以借鉴我的这篇笔记,希望对大家有帮助. 笔记有点长,所以分为一,二两个部分: ...

  7. 【备注】【C42】《编写高质量代码:改善Python程序的91个建议》PDF

    内容简介: 在通往"Python技术殿堂"的路上,本书将为你编写健壮.优雅.高质量的Python代码提供切实帮助!内容全部由Python编码的实践组成,从基本原则.惯用法.语法.库 ...

  8. 荐书与免费送书:《编写高质量代码改善 Python 程序的 91 个建议》

    为了学习如何打理好微信公众号,Python猫我关注了好几个python技术公众号.然后发现这些同行们都在免费送资源,或者抽奖送书耶.于是,我也去参与抽奖,竟然侥幸抽中啦一本<Python数据科学 ...

  9. 《编写高质量代码:改善c程序代码的125个建议》——建议2-6:防止无符号整数回绕...

    本节书摘来自华章计算机<编写高质量代码:改善c程序代码的125个建议>一书中的第1章,建议2-6,作者:马 伟 更多章节内容可以访问云栖社区"华章计算机"公众号查看. ...

最新文章

  1. [bzoj3673/3674可持久化并查集加强版]
  2. 细说Asp.net的IP地址屏蔽功能设计
  3. 8. An Introduction to MCMC for Machine Learning (3)
  4. html5 jq图片效果,HTML5 jQuery可左右滑动拖拉的照片处理前后对比界面
  5. 复习Collection_迭代器使用细节_泛型_综合案例
  6. HTML map元素
  7. 一文了解 Kubernetes 中的服务发现
  8. 2.7配置自定义的Formatters
  9. 读取xml数据装配到字典中之应用场景
  10. 用.NET开发MSN聊天机器人
  11. matlab 曲线收敛,BP神经网络学习曲线收敛问题
  12. c语言人民日报排版的代码,人民日报都在玩的排版黑科技,教你1分钟上手!
  13. DB2日期函数DATE函数
  14. 《设计模式沉思录》分享
  15. 杀戮尖塔(Slay the Spire) mod制作 --- 1
  16. 面试官:说一下Redis和MongoDB的区别?
  17. 联想笔记本怎么找计算机放桌面,联想笔记本电脑便签在哪,笔记本电脑便签在哪里?...
  18. VBS 文本歌词粤语拼音翻译
  19. 牛客网暑期ACM多校训练营(第二场)G.transform (二分+思维)
  20. php电商实现自动售货,2020PHP自动售货发卡网程序开源源码 集成多个支付接口

热门文章

  1. shell学习过程中的错误集锦
  2. EtherCAT1.5.2官方文档翻译-第七章
  3. 每日一则----算法----二分查找法
  4. C++——多进程并发与多线程并发
  5. LeetCode 343. Integer Break
  6. 窗体间的跳转传值 1127
  7. laravel-admin form中的switch控件 不改变状态提交后值为0
  8. 搭建Android的jenkins持续集成环境
  9. svn添加到windows服务中
  10. 28-hadoop-hbase入门小程序