zoukankan      html  css  js  c++  java
  • 解读经典《C#高级编程》第七版 Page38-45.核心C#.Chapter2

    前言

    控制流是语言中最基础的部分,我们不谈具体的细节,只讲讲一些关键和有趣的点。

    01

    流控制

    条件语句:if, else if, else

    if语句的使用非常值得细讲,如何是好的使用习惯。有一点非常重要,就是尽可能的避免太多层次的嵌套,这将带来可读性灾难。我自己的原则是,if嵌套一般不超过2层,最多不超过3层。可读性是什么?是指:不只是你自己写的代码你自己能读懂,更重要的是当别人接手你的代码的时候,别人能读懂。

    If嵌套导致的可读性灾难在Java程序里非常常见,我看别人的遗留代码就是这个感受。一个原因是Java没有像C#这样的linq工具,以及一些语法糖,导致很多常用的计算也要自己写if语句实现,这些代码再套在业务代码中,if层次就很多了,还有比如字段定义都需要生成getter和setter方法(我的Java功力太浅薄,看到大家写Java代码都是这么写,但却不能理解为什么一定要遵循这个范儿),取数判断都是getXXX(),导致布尔表达式代码看着一长串,代码太长又导致很多Java程序员会把一个if拆开成多个嵌套的if来写。比如这个if层次达到了4层(这还不算多,我见过七八层的都有,但一时找不到更多嵌套的例子):

    If嵌套层次多会导致什么问题?就是多执行路径的灾难,一个最简单的if else,如果达到3层嵌套,总的可能执行路径就是2*2*2=8。你的程序要保证这8种执行可能性都被考虑到,这导致的结果往往是程序员放弃遵循严谨的逻辑,只考虑正常的业务逻辑,忽略异常的业务逻辑处理。还有些程序员编程习惯不好,只关注if 不关注else,这种程序员的代码里,大量的if语句没有else,往往就隐藏着很多的逻辑地雷。

    对于if else的使用,我的使用习惯是:

    1. 写下if时就要想到else怎么处理,程序员要打造的是一个“执行容器”,控制容器边界是他的基本职责。只完成需求而不关注“容器”边界安全的程序员不是合格的程序员。
    2. 优先处理else,就是先处理异常的逻辑,并return,从而将 if else的写法替换为if return,从而使得if else 嵌套层级-1。一段代码中,先后的多个if语句都使用这种方式,可使嵌套层级持续减少,可能原本需要五六层级的if嵌套,最后只需要一级if语句实现,代码健壮性和可读性大大增强。

    1. 如果某些地方只需要写if不需要else,但业务逻辑比较复杂,不是能很直观的理解时,我会写空else,并在else中加注释,说明为什么else为空。

    条件语句:switch

    有些人不喜欢使用switch,因为if else也能完成switch的功能,因此懒得去分辨该怎么用switch。我对语言(以及框架)的使用原则不是最简单的够用就好,而是为每种语言特性找到适合它的使用场景,并坚持按最佳的使用方式编写代码。Switch的优点是什么?应用于“值相等”的比较,它格式更清晰,写法更简单,可读性更好。

    Switch语法还有一种特殊用法是,多个空case语句以使多个值条件下执行同一段代码:

    switch(str)

    {

        case "0":

        case "1":

            break;

        default:

            break;

    }

    循环语句:for,while,do…while,foreach

    用的最多的,应该是foreach了,因为循环一个List是当今编写C#代码中最常用的操作了。当你想使用集合的行号时,foreach就不够用了,要用for语句了。非List的循环则会用while,而do…while我很少用,不是它不好用,而是while用习惯了,往往想不起去用do…while。这其实也是在提醒我们:为语言(和类库)特性找到适合它的可明确表述的使用场景是很重要的,因为只有这个意识植入了你心底里,才能在编程中自如的使用最合适的语言特性和类库工具,而不是“都行”,如果遵循的是“都行”的态度,逐渐的你会偏向只使用一种最简单的特性和工具。

    循环还有几个小知识点:

    For,foreach中的变量可以使用类型推断var,比如:

    foreach(var user in list)

    for(var i=0; i< 100; i++)

    for循环可初始化多个值,比如:

    for (int i = 0, j = 0; i < 100; i++, j = j + 2)

    foreach循环集合时,不能更改集合项的值。如果要修改,可以使用for循环代替。但如果要在循环中删除集合的某项,for循环也不行了,这个时候可以将集合进行“变身”,使得循环的“集合”和要处理的“集合”成为两个不同的集合,是个技巧,比如:

    跳转语句:goto

    C#中我从来没用过goto。可以说c#中使用goto几乎没有什么优点,唯一的一个明显用途,是跳出双层循环(后面有例子),goto使得跳出双层循环非常方便,否则我们得自己使用一个独立变量来控制跳出双层循环。

    跳转语句:break

    Break用于退出switch,以及退出for,foreach,while,do…while的循环。

    跳转语句:continue

    Continue用于退出for,foreach,while,do…while的当前迭代。

    跳转语句:return

    Return用于退出类的方法。

    我们对比.Net和Java的语法,发现在goto、break、continue上是有区别的。Java没有goto,而使用了break和continue的功能加强来替代goto的功能。而C#保留了goto,且不提供Java中break和continue中加强的功能。

    .Net:

    Java:

     

    哪种方式更好呢?我更喜欢.Net的处理方式。.Net从实用主义出发,更直观,但可能有些程序员会过度使用goto。而Java表达了语言开发者对Goto的完美厌恶和彻底禁绝,同时,对continue和break的扩展思路非常精妙(但break label稍稍有点别扭)。

    本来还想讲枚举,结果发现流控制也讲了不少,那么枚举到下一篇再讲。

    枚举概念很简单,但我觉得有必要讨论的是枚举它简单的语言定义,和它在实际应用时存在的鸿沟,应该如何填平的问题。

    觉得文章有意义的话,请动动手指,分享给朋友一起来共同学习进步。

    欢迎关注本人微信公众号,更及时的关注最新文章(每周三篇原创文章,以及多篇专题文章):

    附文:

    C#中的&、&&、|、||的区别

    详解C#break ,continue, return

    上一篇:解读经典《C#高级编程》第七版 Page32-38.核心C#.Chapter2

  • 相关阅读:
    指针与数组关联导致的一些现象 分类: H_HISTORY 20130211 20:14 516人阅读 评论(0) 收藏
    宏定义一些内容 分类: H_HISTORY 20130207 23:20 585人阅读 评论(0) 收藏
    使用lstat()判断文件类型 分类: H_HISTORY 20130224 11:48 703人阅读 评论(0) 收藏
    关于VMware虚拟机的上网 分类: C_OHTERS 20130220 14:36 336人阅读 评论(0) 收藏
    Segmentation fault (core dumped) 分类: H_HISTORY 20130206 11:34 18800人阅读 评论(0) 收藏
    C语言内存分配时间 分类: H_HISTORY 20130211 10:51 1432人阅读 评论(3) 收藏
    GTK+与QT的对比 分类: H_HISTORY 20130205 09:27 3101人阅读 评论(0) 收藏
    枚举作为整数 分类: H_HISTORY 20130208 11:22 576人阅读 评论(0) 收藏
    01背包问题,动态规划求解
    求两个字符串的相似度或子串
  • 原文地址:https://www.cnblogs.com/holyknight17/p/10191896.html
Copyright © 2011-2022 走看看