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

所属分类: 网络编程 / 相关技巧 阅读数: 683
收藏 0 赞 0 分享

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

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

1、概述

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

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

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

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

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

我们再来看一下两段代码的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.Phones
          select r.PhoneName;
 
  var result = phones.Where(r => r.StartsWith(prefix));
  return result;
}
public IEnumerable<string> 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<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、总结

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

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

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

更多精彩内容其他人还在看

firefox 扩展开发技巧

firefox 扩展开发
收藏 0 赞 0 分享

php asp.net 比较 [推荐]

如今当提到 Web 开发时,您有许多选择。这些方法中许多都涉及到预处理 - 即,利用特定的标记将代码嵌入到 HTML 页面中
收藏 0 赞 0 分享

UTF-8 BOM 可能导致样式错乱的解决方法

utf-8 是一种在web应用中经常使用的一种 unicode 字符的编码方式,使用 utf-8 的好处在于它是一种变长的编码方式,对于 ANSII 码编码长度为1个字节,这样的话在传输大量 ASCII 字符集的网页时,可以大量节约网络带宽。
收藏 0 赞 0 分享

Web 开发常用工具 大家自己查找下载

看到了Web通信分析工具 这篇文章,除了burpsuite其他我日常都经常使用。于似乎我整理了一下我自己用的其他的WEB开发工具。
收藏 0 赞 0 分享

遇到不能复制的网站怎么办?

有时我们看到喜欢的网页内容时定会产生复制下来为我所用的冲动,不过当你点击鼠标时它却没有任何反应,选择的内容没有任何变化,不禁有点扫兴。不要紧,办法总比困难多!
收藏 0 赞 0 分享

URL 长度有限制吗?

众所周知, 传递小量参数(在没有其他原因,例如隐藏参数值的情况下)推荐使用GET方法,传递大量参数推荐使用POST方法。原因是什么呢?
收藏 0 赞 0 分享

声音验证码制作方法

收听验证码已经比较普遍了,使用户看不清楚的情况下可以通过耳朵来收听验证码,但网上搜了很久没看到有具体的制作方法,自己想了想,还是按自己的方法来实现了,呵呵。
收藏 0 赞 0 分享

防范SQL注入式攻击

SQL注入式攻击是利用是指利用设计上的漏洞,在目标服务器上运行Sql命令以及进行其他方式的攻击动态生成Sql命令时没有对用户输入的数据进行验证是Sql注入攻击得逞的主要原因。
收藏 0 赞 0 分享

Web 设计与开发者必须知道的 15 个站点

今天读到一篇文章,介绍了15个对 Web 设计与开发师极端有用的站点,里面有不少也是我们一直在使用的,也许对很多人都有用,翻译出来以饷同仁。
收藏 0 赞 0 分享

十分钟内学会 避免用户刷新导致重复POST提交

在Web应用中,采用POST提交信息是非常常见的,然而如果目标页面打开得太慢,用户就可能会刷新页面,这时候之前已经提交过的信息就会被重复提交。
收藏 0 赞 0 分享
查看更多