表达式的定义

  • 什么是表达式(其他语言对表达式的定义)

image.png

  • C#语言对表达式的定义

image.png

  • 示例:

    1. static void Main(string[] args)
    2. {
    3. int x;
    4. x = 100;//赋值表达式,得到的结果是一个single value。
    5. new Form();//new表达式,操作符为new,操作数为Form类型,得到的结果是一个对象object
    6. Action action = new Action(Console.WriteLine);
    7. //Console.WriteLine是成员访问表达式,操作符为".",操作数为Console类型和WriteLine类型成员
    8. //得到的结果是一个方法method
    9. System.Windows.Forms.Form myForm = new Form();
    10. //System.Windows是名称空间访问表达式,操作符为".",操作数System主名称空间,Windows是子名称空间
    11. //得到的结果是一个名称空间
    12. int y;
    13. y = 5;//5是一个字面值,参与构成表达式
    14. double a = Math.Pow(2, 3);//Math.Pow(2, 3)是一个函数调用,也是一个表达式
    15. int z = 2 + 6;// 2 + 6是由操作符和操作数构成的一个表达式
    16. int b = 100, c;
    17. c = b;//b是一个变量名simple name,参与构成表达式
    18. }

各类表达式概览

  • C#语言中表达式的分类

image.png

  • 复合表达式的求值
    • 由多个小表达式组成
    • 注意操作符的优先级和同优先级操作符的运算方向
  • 参考C#语言定义文档(第7章)
    • 仅做参考,不必深究——我们是在学习语言,不是去实现这门语言

语句的定义

  • Wikipedia对语句的定义

image.png

  • 查看C#编译好后的低级语言代码:
    • 在win下打开developer command prompt for vs 2019,
    • 在窗口写入ildasm
    • 在弹出的界面,文件中打开C#debug下的应用程序文件
    • 双击方法即可查看低级语言代码
    • 如下图

image.png

  • C#语言对语句的定义

image.png

  • 示例:
    ```csharp using System; using System.Windows.Forms;//这是using指令,而非语句

namespace StatementsExample { class Program { static void Main(string[] args) { var x = 100;//在方法体内,这才是一个语句 } }

class Student
{
    public int ID;//这是字段声明,而非语句
}

}


<a name="e3YZa"></a>
# 语句详解

- C#一共有如下几种语句
- 其中using语句用于接口,yield语句用于集合,lock语句用于多线程,属于较高阶的内容,本文不阐述
- 空语句,标签语句,checked/unchecked语句实际工作中很少用,也不进行阐述

![image.png](https://cdn.nlark.com/yuque/0/2021/png/21507654/1623243932548-7fe8f550-7f8f-4276-8821-2f0385603c34.png#clientId=uc6e77cf1-09f7-4&from=paste&height=608&id=u0e51f61d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=608&originWidth=995&originalType=binary&ratio=1&size=550404&status=done&style=none&taskId=ub2bf129a-0243-449d-ba36-74906620148&width=995)

<a name="d3lDw"></a>
## 声明语句

- 局部变量声明

![image.png](https://cdn.nlark.com/yuque/0/2021/png/21507654/1623244275001-1cd165ee-51ed-4312-b8a2-ad12f3231413.png#clientId=uc6e77cf1-09f7-4&from=paste&height=455&id=u2b793798&margin=%5Bobject%20Object%5D&name=image.png&originHeight=455&originWidth=603&originalType=binary&ratio=1&size=173164&status=done&style=none&taskId=u37cbf982-0ded-4766-9aa6-875ce38c950&width=603)

- 局部常量声明

![image.png](https://cdn.nlark.com/yuque/0/2021/png/21507654/1623244494264-d08a6b9f-bb2b-4219-bf3e-054e05715668.png#clientId=uc6e77cf1-09f7-4&from=paste&height=275&id=udd0256b7&margin=%5Bobject%20Object%5D&name=image.png&originHeight=275&originWidth=571&originalType=binary&ratio=1&size=114805&status=done&style=none&taskId=ub8c22b07-7ad2-4604-bd9a-f7cbe9bbc8a&width=571)

- 示例:
```csharp
static void Main(string[] args)
{
    var x = 100;//局部变量声明语句,"=100"是初始化,而非赋值,和下面分开写是不同的

    int a;//局部变量声明语句
    a = 100;//赋值语句

    const int b = 100;//局部常量申明语句
}

表达式语句

  • 《C#语言规范》文档的定义:

image.png

  • 示例:
    static void Main(string[] args)
    {
      Console.WriteLine("Hello");//方法调用表达式语句invocation-expression
      new Form();//对象创建表达式语句object-creation-expression
      int x;//声明语句
      x = 100;//赋值语句assignment
      x++;//后置++表达式语句post-increment-expression
      x--;//后置--表达式语句post-decrement-expression
      ++x;//前置++表达式语句pre-increment-expression
      --x;//后置--表达式语句pre-decrement-expression
    }
    

块语句

  • 《C#语言规范》文档的定义:

image.png

  • 常配合选择语句、循环语句等一起使用,单独使用较少,且内部变量是有作用域的
  • 示例: ```csharp using System;

namespace StatementsExample {// <—— 此花括号为名称空间体,而非块语句 class Program {// <—— 此花括号为类体,而非块语句 static void Main(string[] args) {// <—— 此花括号为方法体,而非块语句 {// <—— 此花括号为块语句 int x = 100;//声明语句,在块语句外无法使用x,x是有作用域的 if (x>80) Console.WriteLine(x);//嵌入式语句 hello: Console.WriteLine(“hello!”);//标签语句 goto hello;//goto语句,结果为不停地输出hello } } } }


<a name="ZgrLn"></a>
## 选择(判断、分支)语句

- 定义:

![image.png](https://cdn.nlark.com/yuque/0/2021/png/21507654/1623286440740-41ac88b0-946b-4e39-9eea-f05d7987b6e6.png#clientId=u3a0c0d98-d776-4&from=paste&height=78&id=u9bfa34d3&margin=%5Bobject%20Object%5D&name=image.png&originHeight=155&originWidth=634&originalType=binary&ratio=2&size=76790&status=done&style=none&taskId=u179ce764-f868-4faa-a899-d7ac4a450d0&width=317)
<a name="eC8eJ"></a>
### if语句

- 《C#语言规范》文档的定义:

![image.png](https://cdn.nlark.com/yuque/0/2021/png/21507654/1623286486706-2a175075-d07d-4521-bc67-302568c73dc8.png#clientId=u3a0c0d98-d776-4&from=paste&height=215&id=uf1dfe60e&margin=%5Bobject%20Object%5D&name=image.png&originHeight=429&originWidth=870&originalType=binary&ratio=2&size=204588&status=done&style=none&taskId=u097d7a80-6709-4519-af07-c9e7b6c5057&width=435)

- 示例1:if定义解释及注意点
```csharp
static void Main(string[] args)
{
    if (5 > 3) Console.WriteLine("hello!");
    //以上为if语句,根据定义"()"内是一个布尔表达式,其后是一个嵌入式语句
    //"Console.WriteLine("hello!");"是一个表达式语句,属于嵌入式语句,所以整体是if语句
    //为了增强代码的可读性,写成如下
    if (5 > 3)
        Console.WriteLine("hello!");

    int x = 200;
    int y = 100;
    if (x < y)
        Console.WriteLine("hello");
    Console.WriteLine("world");
    //输出world。故意把"Console.WriteLine("world");"缩进,它并不属于if语句,因为if语句只能包含一个嵌入式语句
    //如果想两个都不输出,将它们都写在块语句即可,因为块语句也是嵌入式语句。如下:
    if (x < y)
    {
        Console.WriteLine("hello");
        Console.WriteLine("world");
    }
    else
    {
        Console.WriteLine("hello,world");
    }
}
  • 示例2: 现有一个需求,如果成绩在80-100分,输出A;在60-79分,输出B;在40-59分,输出C;在0-39分,输出D。

    static void Main(string[] args)
    {
      int score = 60;
      if (score >= 80 && score <= 100)
      {
          Console.WriteLine("A");
      }
      else
      {
          if (score >= 60 && score < 80)
          {
              Console.WriteLine("B");
          }
          else
          {
              if (score >= 40 && score < 60)
              {
                  Console.WriteLine("C");
    
              }
              else
              {
                  if (score >= 0 && score < 40)
                  {
                      Console.WriteLine("D");
                  }
                  else
                  {
                      Console.WriteLine("input error!");
                  }
              }
          }
      }
    }
    

    对以上代码进行改写,因为if…else…语句为一个判断语句,所以在else里面的”{}”可以省略,如下:

    static void Main(string[] args)
    {
      int score = 60;
      if (score >= 80 && score <= 100)
      {
          Console.WriteLine("A");
      }
      else if (score >= 60 && score < 80)
      {
          Console.WriteLine("B");
      }
      else if (score >= 40 && score < 60)
      {
          Console.WriteLine("C");
    
      }
      else if (score >= 0 && score < 40)
      {
          Console.WriteLine("D");
      }
      else
      {
          Console.WriteLine("input error!");
      }
    }
    

switch语句

  • 《C#语言规范》文档的定义:

image.png

  • 示例1:需求,80-100输出A;60-79输出B;40-59输出C;0-39输出D,其他输出error

    static void Main(string[] args)
    {
      int score = 90;
      switch (score / 10)//score不能为double类型
      {
          case 10://case后面必须是常量表达式
              if (score == 100)
              {
                  goto case 8;
              }
              else
              {
                  goto default;
              }
          case 8:
          case 9:
              Console.WriteLine("A");
              break;
          case 6:
          case 7:
              Console.WriteLine("B");
              break;
          case 4:
          case 5:
              Console.WriteLine("C");
              break;
          case 3:
          case 2:
          case 1:
          case 0:
              Console.WriteLine("D");
              break;
          default:
              Console.WriteLine("error!");
              break;
      }
    }
    
  • 示例2:enum与switch配合使用 ```csharp using System;

namespace StatementsExample { class Program { static void Main(string[] args) { Level myLevel = Level.High; switch (myLevel)//当敲入myLevel,按回车时,以下代码自动会键入,后续在相应case内加逻辑即可 { case Level.High: Console.WriteLine(“High”);//后加代码 break; case Level.Mid: Console.WriteLine(“Mid”);//后加代码 break; case Level.Low: Console.WriteLine(“Low”);//后加代码 break; default: break; } } }

enum Level
{
    High,
    Mid,
    Low
}

}


<a name="nDKfu"></a>
## try...catch...finally语句

- 《C#语言规范》文档的定义:

![image.png](https://cdn.nlark.com/yuque/0/2021/png/21507654/1623293598418-d4a4cb46-c71e-4e25-b946-619e77ad02a0.png#clientId=u3a0c0d98-d776-4&from=paste&height=352&id=u0ae432f0&margin=%5Bobject%20Object%5D&name=image.png&originHeight=703&originWidth=966&originalType=binary&ratio=2&size=397679&status=done&style=none&taskId=uf99dd646-11ee-40f1-a3b3-635879e2652&width=483)

- 对各种异常类型,可以查MSDN文档
- finally语句,多用于以下两个地方
   - 用于数据库调用,无论有无异常,都会执行finally内语句,用于关闭数据库连接
   - 用于log日志提示,执行记录
- throw:表示不处理异常,将异常抛出,抛出对象为调用者,调用者进行异常处理。
- 示例:
```csharp
using System;

namespace StatementsExample
{
    class Program
    {
        static void Main(string[] args)
        {
            Calculator cal = new Calculator();
            Console.WriteLine(cal.Add(null, "100"));//输出:值不能为 null。参数名: String
            Console.WriteLine(cal.Add("abc","100"));//输出:输入字符串的格式不正确。

            int r = 0;
            try
            {
                r = cal.Add("999999999999999", "100");
            }
            catch (OverflowException oe)
            {
                Console.WriteLine(oe.Message);//输出:值对于 Int32 太大或太小。
            }
            Console.WriteLine(r);
        }
    }

    class Calculator
    {
        public int Add(string arg1,string arg2)
        {
            int a = 0;
            int b = 0;
            bool hasError = false;
            try
            {
                a = int.Parse(arg1);
                b = int.Parse(arg2);
            }
            catch(ArgumentException ane)
            {
                Console.WriteLine(ane.Message);
                hasError = true;
            }
            catch(FormatException fe)
            {
                Console.WriteLine(fe.Message);
                hasError = true;
            }
            catch (OverflowException oe)
            {
                hasError = true;
                throw oe;
                //Console.WriteLine(oe.Message);
            }
            finally
            {
                //用于区分计算后的0是正确的0+0,还是异常的0
                if (hasError)
                {
                    Console.WriteLine("Execution has error!");
                }
                else
                {
                    Console.WriteLine("Done!");
                }
            }
            int result = a + b;
            return result;
        }
    }
}

迭代(循环)语句

  • 迭代语句功能:重复执行嵌入语句
  • 包括以下四种语句:
    • while语句
    • do语句
    • for语句
    • foreach语句

while语句

  • while语句功能:按不同条件执行一个嵌入语句零次或多次
  • while语句格式如下:

image.png

  • 示例:有一个算术运算的小游戏,当输出两个值的和为100时,就加1分,并继续进行下一轮,直到不等于100时,结束游戏。

    static void Main(string[] args)
    {
      int score = 0;
      bool canContinue = true;
      while (canContinue)
      {
          Console.WriteLine("请输入第一个数字:");
          string str1 = Console.ReadLine();
          int x = int.Parse(str1);
    
          Console.WriteLine("请输入第二个数字:");
          string str2 = Console.ReadLine();
          int y = int.Parse(str2);
    
          int sum = x + y;
          if (sum == 100)
          {
              score++;
              Console.WriteLine($"正确!{x}+{y}={sum}");
          }
          else
          {
              Console.WriteLine($"错误!{x}+{y}={sum}");
              canContinue = false;
          }
      }
      Console.WriteLine($"你的分数是{score}");
      Console.WriteLine("游戏结束!");
    }
    

do语句

  • do语句功能:按不同条件执行一个嵌入语句一次或多次
  • do语句格式如下:

image.png

  • 示例:将以上代码用do语句进行优化,如下:

    static void Main(string[] args)
    {
      int score = 0;
      int sum = 0;
      do
      {
          Console.WriteLine("请输入第一个数字:");
          string str1 = Console.ReadLine();
          int x = int.Parse(str1);
    
          Console.WriteLine("请输入第二个数字:");
          string str2 = Console.ReadLine();
          int y = int.Parse(str2);
    
          sum = x + y;
          if (sum == 100)
          {
              score++;
              Console.WriteLine($"正确!{x}+{y}={sum}");
          }
          else
          {
              Console.WriteLine($"错误!{x}+{y}={sum}");
          }
      } while (sum == 100);
      Console.WriteLine($"你的分数是{score}");
      Console.WriteLine("游戏结束!");
    }
    

for语句

  • for语句功能:用于计数循环,计算一个初始化表达式序列,然后,当某个条件为真时,重复执行相关的嵌入语句并计算一个迭代表达式序列
  • for语句格式:

image.png

  • 示例1:在屏幕打印10次hello,world

    static void Main(string[] args)
    {
      //使用while语句输出10次hello,world
      int count = 0;
      while (count < 10)
      {
          Console.WriteLine("hello,world");
          count++;
      }
    
      Console.WriteLine("================================");
      //使用for语句输出10次hello,world
      for (int i = 0; i < 10; i++)
      {
          Console.WriteLine("hello,world");
      }
    }
    
  • 示例2:在屏幕打印九九乘法表

    static void Main(string[] args)
    {
      for (int i = 1; i <= 9; i++)
      {
          for (int j = 1; j <= i; j++)
          {
              Console.Write($"{i}*{j}={i * j}\t");
          }
          Console.WriteLine();
      }
    }
    

foreach语句

  • foreach语句功能:用于枚举一个集合的元素,并对该集合中的每个元素执行一次相关的嵌入语句
  • foreach语句格式:

image.png

  • 所有实现IEnumerable接口的类都是可被遍历的集合,foreach语句就是对集合遍历的一种简记法
  • 示例:集合遍历的底层原理和迭代器

    static void Main(string[] args)
    {
      //使用迭代器对集合进行遍历
      int[] intArr = new int[] { 1, 2, 3, 4, 5 };
      //或 List<int> intList = new List<int>() { 1, 2, 3, 4, 5 };
      IEnumerator enumerator = intArr.GetEnumerator();
      while (enumerator.MoveNext())
      {
          Console.WriteLine(enumerator.Current);
      }
    
      enumerator.Reset();//此处把集合拨回最开始,以便后面能继续遍历
      while (enumerator.MoveNext())
      {
          Console.WriteLine(enumerator.Current);
      }
    
      //使用foreach对集合进行遍历
      List<int> intList = new List<int>() { 1, 2, 3, 4, 5, 6 };
      foreach (var item in intList)
      {
          Console.WriteLine(item);
      }
    }
    

跳转语句

  • 跳转语句功能:用于无条件地转移控制
  • 包括以下五种语句:
    • break语句
    • continue语句
    • goto语句
    • return语句
    • throw语句

continue语句

  • continue语句功能:放弃当前循环,立即开始一次新的循环
  • continue语句将开始直接封闭它的while,do,for,或foreach语句的一次新迭代
  • continue语句格式如下:

image.png

  • 示例:do示例中存在2个地方有风险,当输入值不是数字整型字符串时,会报异常,需要捕捉异常后提示重新输入,将”int x = int.Parse(str1);”进行改写,如下:

    static void Main(string[] args)
    {
      int score = 0;
      int sum = 0;
      do
      {
          Console.WriteLine("请输入第一个数字:");
          string str1 = Console.ReadLine();
          int x = 0;
          try
          {
              x = int.Parse(str1);
          }
          catch
          {
              Console.WriteLine("输入值有问题,请重新输入数字:");
              continue;//放弃当前循环,立即开始新的循环
          }
    
          Console.WriteLine("请输入第二个数字:");
          string str2 = Console.ReadLine();
          int y = 0;
          try
          {
              y = int.Parse(str2);
          }
          catch
          {
              Console.WriteLine("输入值有问题,请重新输入数字:");
              continue;//放弃当前循环,立即开始新的循环
          }
    
          sum = x + y;
          if (sum == 100)
          {
              score++;
              Console.WriteLine($"正确!{x}+{y}={sum}");
          }
          else
          {
              Console.WriteLine($"错误!{x}+{y}={sum}");
          }
      } while (sum == 100);
      Console.WriteLine($"你的分数是{score}");
      Console.WriteLine("游戏结束!");
    }
    

break语句

  • break语句功能:立即结束循环语句,将退出直接封闭它的while,do,for,或foreach语句
  • break语句格式如下:

image.png

  • 示例:还是前面的算术小游戏,新增功能,当小朋友想结束游戏,又不想估计输错数值,使用end来结束。

    static void Main(string[] args)
    {
      int score = 0;
      int sum = 0;
      do
      {
          Console.WriteLine("请输入第一个数字:");
          string str1 = Console.ReadLine();
          if (str1.ToLower() == "end")
          {
              break;//如果输入为end,立即跳出循环
          }
          int x = 0;
          try
          {
              x = int.Parse(str1);
          }
          catch
          {
              Console.WriteLine("输入值有问题,请重新输入数字:");
              continue;//放弃当前循环,立即开始新的循环
          }
    
          Console.WriteLine("请输入第二个数字:");
          string str2 = Console.ReadLine();
          if (str1.ToLower() == "end")
          {
              break;//如果输入为end,立即跳出循环
          }
          int y = 0;
          try
          {
              y = int.Parse(str2);
          }
          catch
          {
              Console.WriteLine("输入值有问题,请重新输入数字:");
              continue;//放弃当前循环,立即开始新的循环
          }
    
          sum = x + y;
          if (sum == 100)
          {
              score++;
              Console.WriteLine($"正确!{x}+{y}={sum}");
          }
          else
          {
              Console.WriteLine($"错误!{x}+{y}={sum}");
          }
      } while (sum == 100);
      Console.WriteLine($"你的分数是{score}");
      Console.WriteLine("游戏结束!");
    }
    

return语句

  • return语句将控制返回到出现return语句的函数成员的调用方
  • 编写代码时应遵循尽早return原则
  • 示例:

    class Program
    {
      static void Main(string[] args)
      {
          Greeting("Mr.Okay");
          var result = WhoIsWho("Mr.Okay");
          Console.WriteLine(result);
      }
    
      static void Greeting(string name)
      {
          if (string.IsNullOrEmpty(name))
          {
              return;
          }
          Console.WriteLine("Hello,{0}!", name);
      }
    
      static string WhoIsWho(string alias)
      {
          if (alias == "Mr.Okay")
          {
              return "Tim";
          }
          return "I don't know!";
      }
    }
    

goto语句

  • goto语句将控制转到由标签标记的语句(前面有示例)
  • goto语句现在实际用的较少
  • goto语句格式如下:

image.png

throw语句

  • throw语句引发一个异常(前面有示例)
  • throw语句灵活多变,后面可不跟参数
  • throw语句格式如下:

image.png