C#入门经典(第7版):C# 6.0 & Visual Studio 2015(.NET开发经典名著)
上QQ阅读APP看书,第一时间看更新

4.2 分支

分支是控制下一步要执行哪行代码的过程。要跳转到的代码行由某个条件语句来控制。这个条件语句使用布尔逻辑,对测试值和一个或多个可能的值进行比较。

本节介绍C#中的3种分支技术:

● 三元运算符

● if语句

● switch语句

4.2.1 三元运算符

最简单的比较方式是使用第3章介绍的三元(或条件)运算符。一元运算符有一个操作数,二元运算符有两个操作数,所以三元运算符有3个操作数。其语法如下:

        <test> ? <resultIfTrue>: <resultIfFalse>

其中,计算<test>可得到一个布尔值,运算符的结果根据这个值来确定是<resultIfTrue>还是<resultIfFalse>。

使用三元运算符可以测试int变量myInteger的值:

        string resultString = (myInteger < 10) ? "Less than 10"
                                          : "Greater than or equal to 10";

三元运算符的结果是两个字符串中的一个,这两个字符串都可能赋给resultString。把哪个字符串赋给resultString,取决于myInteger的值与10的比较结果。如果myInteger的值小于10,就把第一个字符串赋给resultString;如果myInteger的值大于或等于10,就把第二个字符串赋给resultString。例如,如果myInteger的值是4,则resultString的值就是字符串"Less than 10"。

4.2.2 if语句

if语句的功能比较多,是有效的决策方式。与?:语句不同的是,if语句没有结果(所以不在赋值语句中使用它),使用该语句是为了根据条件执行其他语句。

if语句最简单的语法如下:

        if (<test>)
        <code executed if <test> is true>;

先执行<test>(其计算结果必须是一个布尔值,这样代码才能编译),如果<test>的计算结果是true,就执行该语句之后的代码。这段代码执行完毕后,或者因为<test>的计算结果是false,而没有执行这段代码,将继续执行后面的代码行。

也可将else语句和if语句合并使用,指定其他代码。如果<test>的计算结果是false,就执行else语句:

        if (<test>)
          <code executed if <test> is true>;
        else
          <code executed if <test> is false>;

可使用成对的花括号将这两段代码放在多个代码行上:

        if (<test>)
        {
          <code executed if <test> is true>;
        }
        else
        {
          <code executed if <test> is false>;
        }

例如,重新编写上一节使用三元运算符的代码:

    string resultString = (myInteger < 10) ? "Less than 10"
                                      : "Greater than or equal to 10";

因为if语句的结果不能赋给一个变量,所以要单独将值赋给变量:

    string resultString;
    if (myInteger < 10)
      resultString = "Less than 10";
    else
      resultString = "Greater than or equal to 10";

这样的代码尽管比较冗长,但与三元运算符相比,更便于阅读和理解,也更加灵活。

下面的示例演示了if语句的用法。

试一试:使用if语句:Ch04Ex02\Program.cs

(1)在目录C:\BegVCSharp\Chapter04中创建一个新的控制台应用程序Ch04Ex02。

(2)把下列代码添加到Program.cs中:

        static void Main(string[] args)
        {
          string comparison;
          WriteLine("Enter a number:");
          double var1 = ToDouble(ReadLine());
          WriteLine("Enter another number:");
          double var2 = ToDouble(ReadLine());
          if (var1 < var2)
              comparison = "less than";
          else
          {
              if (var1 == var2)
                comparison = "equal to";
              else
                comparison = "greater than";
          }
          WriteLine($"The first number is
                    {comparison} the second number.");
          ReadKey();
        }

(3)执行代码,根据提示输入两个数字,如图4-2所示。

图4-2

示例说明

我们已经十分熟悉代码的第一部分,它从用户输入中得到两个double值:

        string comparison;
        WriteLine("Enter a number:");
        double var1 = ToDouble(ReadLine());
        WriteLine("Enter another number:");
        double var2 = ToDouble(ReadLine());

接着根据var1和var2的值,将一个字符串赋给string变量comparison。首先看看var1是否小于var2:

        if (var1 < var2)
          comparison = "less than";

如果不是,则var1大于或等于var2。在第一个比较操作的else部分,需要嵌套第二个比较:

        else
        {
          if (var1 == var2)
              comparison = "equal to";

只有在var1大于var2时,才执行第二个比较操作中的else部分:

          else
              comparison = "greater than";
        }

最后将比较操作的值写到控制台:

        WriteLine("The first number is {0} the second number.", comparison);

这里使用的嵌套只是进行这些比较的一种方式,还可以编写如下代码:

        if (var1 < var2)
          comparison = "less than";
        if (var1 == var2)
          comparison = "equal to";
        if (var1 > var2)
          comparison = "greater than";

这种方式的缺点在于:无论var1和var2的值是什么,都要执行3个比较操作。在第一种方式中,如果var1 < var2是true,就只执行一个比较操作,否则就要执行两个比较操作(还执行了var1 == var2比较操作),这样将使执行的代码行较少。在本例中性能上的差异较小,但在较重视速度的应用程序中,性能的差异就很明显了。

使用if语句判断更多条件

在上面的示例中,检查了涉及var1的值的3个条件,包括这个变量所有可能的值。有时要检查特定的值,例如var1是否等于1、2、3或4等。使用上面那样的代码会得到很多烦人的嵌套代码:

        if (var1 == 1)
        {
          // Do something.
        }
        else
        {
          if (var1 == 2)
          {
              // Do something else.
          }
          else
          {
              if (var1 == 3 || var1 == 4)
              {
                // Do something else.
              }
              else
              {
                // Do something else.
              }
          }
        }

警告:人们经常会错误地将诸如if(var1== 3 || var1 == 4)的条件写为if (var1 == 3 || 4)。由于运算符具有优先级,因此首先执行==运算符,接着用||运算符处理布尔和数值操作数,就会出现错误。

这些情况下,就要使用稍有不同的缩进模式,缩短else代码块(即在else块的后面使用一行代码而不是一个代码块),这样就得到了else if语句结构:

        if (var1 == 1)
        {
          // Do something.
        }
        else if (var1 == 2)
        {
          // Do something else.
        }
        else if (var1 == 3 || var1 == 4)
        {
          // Do something else.
        }
        else
        {
          // Do something else.
        }

这些else if语句实际上是两个独立语句,它们的功能与上述代码相同,但更便于阅读。像这样进行多个比较的操作,应考虑使用另一种分支结构:switch语句。

4.2.3 switch语句

switch语句非常类似于if语句,因为它也是根据测试的值来有条件地执行代码。但是,switch语句可以一次将测试变量与多个值进行比较,而不是仅测试一个条件。这种测试仅限于离散的值,而不是像“大于X”这样的子句,所以它的用法有点不同,但它仍是一种强大的技术。

switch语句的基本结构如下:

        switch (<testVar>)
        {
          case <comparisonVal1>:
              <code to execute if <testVar> == <comparisonVal1> >
              break;
          case <comparisonVal2>:
              <code to execute if <testVar> == <comparisonVal2> >
              break;
          ..
          case <comparisonValN>:
              <code to execute if <testVar> == <comparisonValN> >
              break;
          default:
              <code to execute if <testVar> ! = comparisonVals>
              break;
        }

<testVar>中的值与每个<comparisonValX>值(在case语句中指定)进行比较,如果有一个匹配,就执行为该匹配提供的语句。如果没有匹配,但有default语句,就执行default部分的代码。

执行完每个部分的代码后,还需要有另一个语句break。在执行完一个case块后,再执行第二个case语句是非法的。

注意:在此,C#与C++是有区别的。在C++中,可以在运行完一个case语句后,运行另一个case语句。

这里的break语句将中断switch语句的执行,而执行该结构后面的语句。

在C#代码中,还有其他方法可以防止程序流程从一个case语句转到下一个case语句。可以使用return语句,中断当前函数的运行,而不是仅中断switch结构的执行(详见第6章)。也可以使用goto语句(如前所述),因为case语句实际上是在C#代码中定义的标签。例如:

        switch (<testVar>)
        {
          case <comparisonVal1>:
              <code to execute if <testVar> == <comparisonVal1> >
              goto case <comparisonVal2>;
          case <comparisonVal2>:
              <code to execute if <testVar> == <comparisonVal2> >
              break;
          ..

一个case语句处理完后,不能自由进入下一个case语句,但这条规则有一个例外。如果把多个case语句放在一起(堆叠它们),其后加一个代码块,实际上是一次检查多个条件。如果满足这些条件中的任何一个,就会执行代码,例如:

        switch (<testVar>)
        {
          case <comparisonVal1>:
          case <comparisonVal2>:
            <code to execute if <testVar> == <comparisonVal1> or
                              <testVar> == <comparisonVal2> >
            break;
          ..

注意,这些条件也适用于default语句。default语句不一定要放在比较操作列表的最后,还可以把它和case语句放在一起。用break或return添加一个断点,可确保在任何情况下,该结构都有一条有效的执行路径。

在下面的示例中,将使用switch语句,根据用户为测试字符串输入的值,将不同字符串写到控制台。

试一试:使用switch语句:Ch04Ex03\Program.cs

(1)在目录C:\BegVCSharp\Chapter04中创建一个新的控制台应用程序Ch04Ex03。

(2)把以下代码添加到Program.cs中:

            static void Main(string[] args)
            {
              const string myName = "benjamin";
              const string niceName = "andrea";
              const string sillyName = "ploppy";
              string name;
              WriteLine("What is your name? ");
              name = ReadLine();
              switch (name.ToLower())
              {
                  case myName:
                    WriteLine("You have the same name as me! ");
                    break;
                  case niceName:
                    WriteLine("My, what a nice name you have! ");
                    break;
                  case sillyName:
                    WriteLine("That's a very silly name.");
                    break;
              }
              WriteLine($"Hello {name}! ");
              ReadKey();
            }

(3)执行代码,输入一个姓名,结果如图4-3所示。

图4-3

示例说明

这段代码建立了3个常量字符串,接受用户输入的一个字符串,再根据输入的字符串把文本写到控制台。这里,字符串是用户输入的姓名。

在比较输入的姓名(在变量name中)和常量值时,首先要用name.ToLower()把输入的姓名转换为小写。name.ToLower()是一个标准命令,可用于处理所有字符串变量,在不能确定用户输入的内容时,使用它是很方便的。使用这个技术,字符串Benjamin、benJamin、benjamin等就会与测试字符串benjamin匹配了。

switch语句尝试将输入的字符串与定义的常量值进行匹配,如果成功,就会用一条个性化的消息问候用户。如果不匹配,则只简单地问候用户。