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

编写高质量代码的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篇文章,为大家提供编写高质量代码的一般准则。

总结

到此这篇关于编写高质量代码的30条黄金守则(首选隐式类型转换)的文章就介绍到这了,更多相关编写高质量代码的30条黄金守则内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 高质量PHP代码的50个实用技巧必备(上)

    50个高质量PHP代码的实用技巧,希望大家喜欢. 1.不要使用相对路径 常常会看到: require_once('../../lib/some_class.php'); 该方法有很多缺点: 它首先查找指定的php包含路径, 然后查找当前目录.因此会检查过多路径.如果该脚本被另一目录的脚本包含, 它的基本目录变成了另一脚本所在的目录. 另一问题, 当定时任务运行该脚本, 它的上级目录可能就不是工作目录了.因此最佳选择是使用绝对路径: view sourceprint? define('ROOT'

  • 如何编写高质量JS代码

    想写出高效的javascript类库却无从下手: 尝试阅读别人的类库,却理解得似懂给懂: 打算好好钻研js高级函数,但权威书上的内容太零散, 即使记住"用法",但到要"用"的时候却没有想"法". 也许你和我一样,好像有一顾无形的力量约束着我们的计划,让我们一再认为知识面的局限性,致使我们原地踏步,难以向前跨越. 这段时间,各种作业.课程设计.实验报告,压力倍增.难得挤出一点点时间,绝不睡懒觉,整理总结往日所看的书,只为了可以离写自己的类库近一点.

  • 高质量Python代码编写的5个优化技巧

    如今我使用 Python 已经很长时间了,但当我回顾之前写的一些代码时,有时候会感到很沮丧.例如,最早使用 Python 时,我写了一个名为 Sudoku 的游戏(GitHub地址:https://github.com/MichaelWashburnJr/PythonSudoku).这个游戏在当时算是我比较拿得出手的项目了.然而现在,我无法直接复制其代码并运行它,具体原因是我当时编码时没有添加一个setup.py 或者 requires.txt 文件,当然,这种错误我肯定不会再犯! 由此,我总结

  • 如何书写高质量jQuery代码(使用jquery性能问题)

    1.正确引用jQuery 1.尽量在body结束前才引入jQuery,而不是在head中. 2.借助第三方提供的CDN来引入jQuery,同时注意当使用第三方CDN出现问题时,要引入本地的jQuery文件.(对于已经使用了cdn的网站可以忽略,现在用户带宽都升级了,这个可以忽略了,放别人机器不一定稳定) 3.如果在</body>前引入script文件的话,就不用写document.ready了,因为这时执行js代码时DOM已经加载完毕了. <body> <script src

  • 详解JAVA高质量代码之数组与集合

    1.性能考虑,优先选择数组 数组在项目开发当中使用的频率是越来越少,特别是在业务为主的开发当中,首先数组没有List,Set等集合提供的诸多方法,查找增加算法都要自己编写,极其繁琐麻烦,但由于List,Set等集合使用泛型支持后,存放的都为包装类,而数组是可以使用基本数据类型,而使用基本数据类型的执行运算速度要比包装类型快得多,而且集合类的底层也是通过数组进行实现. 2.若有必要,使用变长数组 在学习集合类当中,很多人喜欢将数组的定长拿来和集合类型的自变长来做比较,但其实这种比较并不合适,通过观

  • 12条写出高质量JS代码的方法

    书写出高质量的JS代码不仅让程序员看着舒服,更加能够提高程序的运行速度,以下就是我们的小编整理方法: 一.如何书写可维护性的代码 当出现bug的时候如果你能立马修复它是最好的,此时解决问题的四路在你脑中还是很清晰的.否则,你转移到其他任务或者bug是经过一定的时间才出现的,你忘了那个特定的代码,一段时间后再去查看这些代码就 需要: 1.花时间学习和理解这个问题 2.化时间是了解应该解决的问题代码 还有个问题,特别对于大的项目或是公司,修复bug的这位伙计不是写代码的那个人(且发现bug和修复bu

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

    编写高质量代码的30条黄金守则-Day 01(首选隐式类型转换),本文由比特飞原创发布,转载务必在文章开头附带链接:https://www.byteflying.com/archives/6455 该系列文章由比特飞原创发布,计划用三个月时间写完全30篇文章,为大家提供编写高质量代码的一般准则. 1.概述 隐式类型转换是微软为了 C# 支持匿名类型而加入的,使用 var 通常可以使代码的可读性更强,甚至是帮我们解决一些严重的性能问题.为了清楚的明白 var 的作用机制,我们首先来看看编译器为 v

  • 编写高质量代码改善C#程序——使用泛型集合代替非泛型集合(建议20)

    软件开发过程中,不可避免会用到集合,C#中的集合表现为数组和若干集合类.不管是数组还是集合类,它们都有各自的优缺点.如何使用好集合是我们在开发过程中必须掌握的技巧.不要小看这些技巧,一旦在开发中使用了错误的集合或针对集合的方法,应用程序将会背离你的预想而运行. 建议20:使用泛型集合代替非泛型集合 在建议1中我们知道,如果要让代码高效运行,应该尽量避免装箱和拆箱,以及尽量减少转型.很遗憾,在微软提供给我们的第一代集合类型中没有做到这一点,下面我们看ArrayList这个类的使用情况: Array

  • 深入理解javascript学习笔记(一) 编写高质量代码

    一.变量 •全局变量 JavaScript的两个特征,不自觉地创建出全局变量是出乎意料的容易.首先,你可以甚至不需要声明就可以使用变量:第二,JavaScript有隐含的全局概念,意味着你不声明的任何变量都会成为一个全局对象属性(不是真正意义上的全局变量,可以用delete删除) 复制代码 代码如下: function sum(x,y) { // result 未声明,为隐式全局变量 result = x + y; return result; } function foo() { // 使用任

  • 如何编写高质量 JavaScript 代码

    目录 一.易阅读的代码 1.统一代码格式 2.去除魔术数字 3.单一功能原则 二.高性能的代码 1.优化算法 2.使用内置方法 3.减少作用域链查找 4.避免做重复的代码 三.健壮性的代码 1.使用新语法 2.随时可扩展 3.避免副作用 4.整合逻辑关注点 前段时间有一个叫做"人类高质量男性"的视频火了,相信很多同学都刷到过.所以今天给大家分享下,什么叫做"人类高质量代码",哈哈,开个玩笑. 其实分享的都是一些自己平时总结的小技巧,算是抛砖引玉吧,希望能给大家带来一

  • 深入理解JavaScript系列(1) 编写高质量JavaScript代码的基本要点

    具体一点就是编写高质量JavaScript的一些要素,例如避免全局变量,使用单变量声明,在循环中预缓存length(长度),遵循代码阅读,以及更多. 此摘要也包括一些与代码不太相关的习惯,但对整体代码的创建息息相关,包括撰写API文档.执行同行评审以及运行JSLint.这些习惯和最佳做法可以帮助你写出更好的,更易于理解和维护的代码,这些代码在几个月或是几年之后再回过头看看也是会觉得很自豪的. 书写可维护的代码(Writing Maintainable Code ) 软件bug的修复是昂贵的,并且

  • 编写高质量JavaScript代码的基本要点

    才华横溢的Stoyan Stefanov,在他写的由O'Reilly初版的新书<JavaScript Patterns>(JavaScript模式)中,我想要是为我们的读者贡献其摘要,那会是件很美妙的事情.具体一点就是编写高质量JavaScript的一些要素,例如避免全局变量,使用单变量声明,在循环中预缓存length(长度),遵循代码阅读,以及更多. 此摘要也包括一些与代码不太相关的习惯,但对整体代码的创建息息相关,包括撰写API文档.执行同行评审以及运行JSLint.这些习惯和最佳做法可以

  • 如何编写高质量JS代码(续)

    继续上一篇文章<如何编写高质量JS代码>今次整理一下javascript函数知识点. 2.使用函数 函数给程序员提供了主要的抽象功能,又提供实现机制.函数可以独立实现其他语言中的多个不同的特性,例如,过程.方法.构造函数,甚至类或模块. 2.1 理解函数调用.方法调用以及构造函数调用之间的不同 针对面向对象编程,函数.方法和类的构造函数是三种不同的概念. 使用模式: 1,函数调用 复制代码 代码如下: function hello(username){     return "hel

  • 写出高质量软件的75条体会

    如何用正确的方法写出高质量软件的75条体会 1. 你们的项目组使用源代码管理工具了么? MVM:应该用.VSS.CVS.PVCS.ClearCase.CCC/Harvest.FireFly都可以.我的选择是VSS. 2. 你们的项目组使用缺陷管理系统了么? MVM:应该用.ClearQuest太复杂,我的推荐是BugZilla. 3. 你们的测试组还在用Word写测试用例么? MVM:不要用Word写测试用例(Test Case).应该用一个专门的系统,可以是Test Manager,也可以是自

  • 编写高性能Javascript代码的N条建议

    多年来,Javascript一直在web应用开发中占据重要的地位,但是很多开发者往往忽视一些性能方面的知识,特别是随着计算机硬件的不断升级,开发者越发觉得Javascript性能优化的好不好对网页的执行效率影响不明显.但在某些情况下,不优化的Javascript代码必然会影响用户的体验.因此,即使在当前硬件性能已经大大提升的时代,在编写Javascript代码时,若能遵循Javascript规范和注意一些性能方面的知识,对于提升代码的可维护性和优化性能将大有好处. 下面给出编写高性能的Javas

  • 详解如何把Java中if-else代码重构成高质量代码

    为什么我们写的代码都是if-else? 程序员想必都经历过这样的场景:刚开始自己写的代码很简洁,逻辑清晰,函数精简,没有一个if-else, 可随着代码逻辑不断完善和业务的瞬息万变:比如需要对入参进行类型和值进行判断:这里要判断下对象是否为null:不同类型执行不同的流程. 落地到具体实现只能不停地加if-else来处理,渐渐地,代码变得越来越庞大,函数越来越长,文件行数也迅速突破上千行,维护难度也越来越大,到后期基本达到一种难以维护的状态. 虽然我们都很不情愿写出满屏if-else的代码,可逻

随机推荐