image.png

●表达式的定义

image.png

evaluate a single value, object, method, or namespace

释义:计算单个值、对象、方法或名称空间

Single Value 单值

image.png

Object 对象

image.png

Method 方法

image.png

Namespace 命名空间

image.png

●各类表达式概览

(10)表达式 语句详解 - 图7

A Value 一个值

A value. Every value has an associated type. 一个值。每个值都有一个关联的类型。
回顾上一节讲的操作符,并讲解由这些操作符组成的表达式所返回的类型。
(10)表达式 语句详解 - 图8

条件操作符 ?: 总会返回精度高的那个类型。

A variable 变量

A variable. Every variable has an associated type.一个变量。 每个变量都有一个关联的类型。
image.png

A namespace 命名空间

image.png

A type 类型

image.png

A method group 方法组

Console.WriteLine,这是一组方法(19 种重载),重载决策决定具体调用那种方法。

A null literal 空值

null 值也是一个值。image.png

An anonymous function 匿名方法

image.png

A property access 属性访问

image.png

An event access 访问时间

image.pngimage.png

An indexer access 访问索引器

image.png

Nothing 返回值为void的方法调用

image.png 没有返回任何值

复合表达式的求值

C#语言定义文档里面未明确定义复合表达式,但确实常用。
注意操作符的优先级和同优先级操作符的运算方向(除了赋值操作符,基本都是从左向右)。

参考C#语言定义文档

对于初学者,仅作参考,不必深究 —— 毕竟我们是在学习语言、不是去实现这门语言。

●语句的定义

广义:

语句:对应着一组指令(通过汇编观察)
(10)表达式 语句详解 - 图19
image.png

实例讲解高级语言与低级语言的差异

C 版本
(10)表达式 语句详解 - 图21(10)表达式 语句详解 - 图22
(10)表达式 语句详解 - 图231656520592932.png
C# 版本
(10)表达式 语句详解 - 图25
(10)表达式 语句详解 - 图26
(10)表达式 语句详解 - 图27

狭义:

语句:陈述算法思想,控制逻辑走向,完成有意义的动作。
(10)表达式 语句详解 - 图28

实例演示控制流

我们的代码没有变,只是执行顺序及分支变了。 尽管语句是固定的,但每次执行的时代,根据输入数据的不同,控制流(执行流)有可能不一样。

image.pngimage.png

●语句详解

(10)表达式 语句详解 - 图31

嵌入式语句案例: (10)表达式 语句详解 - 图32

声明语句

讲解了局部变量声明与局部常量声明,详情参见 C#语言定义文档。
(10)表达式 语句详解 - 图33

表达式语句

(10)表达式 语句详解 - 图34
expression-statement 用于计算所给定的表达式。由此表达式计算出来的值(如果有)被丢弃。
image.png
Single Responsibility 单一职责原则:一个方法尽量只做一件事情。

下面 x+y 这种语句在 C 语言里面是允许的,在 C# 里面不允许。(无法编译过去) image.png

块语句

(10)表达式 语句详解 - 图37

● 块语句无论什么时候都被编译器当做一条语句来看待 ● 编译器认为块语句是一条完整的语句(即块语句最后不用加;号)

Code Snippet
Ctrl + }:跳转至该花括号对应的花括号处。

image.pngimage.png

选择(判断、分支)语句

(10)表达式 语句详解 - 图40

if 语句

(10)表达式 语句详解 - 图41

●编程规范推荐即使只有一条语句,也建议使用块语句。为什么?↓

Code Snippet image.pngimage.pngimage.png 此处条件只控制了第一行语句 √ (每条语句只能有一条嵌入式语句)

程序员经常修缮前人代码以满足新需求,但因为需求变化(需要实现新逻辑) + 业务逻辑复杂(不敢修改旧代码),导致写出来的代码很臃肿,还很容易陷入思维定式。
无论多长的 if else,它都是一条语句。之所以能有 else if{} 这种结构,也是因为 if{} 是一条语句。案例如下:
image.png(逐级筛选) 演变成 (else if 语句) image.png

switch 语句

(10)表达式 语句详解 - 图47
注:从 C# 7.0 开始 switch 表达式已支持任何非 null 表达式
image.png

Code Snippet

  1. Ctrl + L 剪切一整行
  2. (10)表达式 语句详解 - 图49

Try语句

(10)表达式 语句详解 - 图50
可以通过 MSDN 查方法相应的异常。

如 Int32.Parse 方法 (String) 就有以下异常。

(10)表达式 语句详解 - 图51

  • 应该把释放系统资源的语句写在 finally block 里面
  • 有时候也在 finally block 里面写 log

image.pngimage.pngimage.png
粗略异常处理 精细异常处理 完整格式
● throw 将异常抛给调用者。(谁调用谁处理)

throw抛出异常案例如下:

image.pngimage.png
image.png
● throw 关键字的语法比较灵活。

  1. try{
  2. ...
  3. }
  4. catch(OverflowException){
  5. throw;
  6. }

迭代(循环)语句

while语句

  • while 语句按不同条件执行一个嵌入语句零次或多次

image.png

do语句

  • do 语句按不同条件执行一个嵌入语句一次或多次

image.png
image.png

for语句

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

image.png
执行顺序(重点):左→(中→内部代码→右)→重复括号内部逻辑

for 循环圆括号里面的的三部分都是 opt 可选的(两个分号不能省略),由此可以组成许多平时用不到的奇葩结构。

image.png

拓展:遍历和迭代器

① C#所有的数组类型基类都是Array。 ②C#中所有实现了IEnumerable接口的类就是可以被遍历的集合。

Array 实现了 IEnumerable
(10)表达式 语句详解 - 图63
(10)表达式 语句详解 - 图64
(10)表达式 语句详解 - 图65
什么是迭代器?
1656613581711.png
集合遍历的底层原理和迭代器,foreach 语句就是对集合遍历的简记法。

  1. static void Main(string[] args)
  2. {
  3. var intArray = new int[] { 1, 3, 5 ,7};
  4. IEnumerator enumerator = intArray.GetEnumerator();
  5. while (enumerator.MoveNext())
  6. {
  7. Console.WriteLine(enumerator.Current);
  8. }
  9. var intList = new List<int>() { 2, 4, 6, 8 };
  10. IEnumerator enumerator2 = intList.GetEnumerator();
  11. while (enumerator2.MoveNext())
  12. {
  13. Console.WriteLine(enumerator2.Current);
  14. }
  15. }

foreach语句

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

    跳转语句

    continue语句

  • continue 语句将开始直接封闭它的 while、do、for 或 foreach 语句的一次新迭代

    放弃当前循环,开启新的循环。

image.png

break语句

  • break 语句将退出直接封闭它的 switch、while、do、for 或 foreach 语句

    立刻结束循环,不再进入循环。

image.png

goto语句

  • goto 语句将控制转到由标签标记的语句

    • goto 语句基本被淘汰

      throw语句

  • throw 语句将引发一个异常

    • throw 语句语法比较灵活,它后面可以什么都不跟

      return语句

  • return 语句会将控制返回到出现 return 语句的函数的当前调用方

    • 提前 return 原则
    • 方法的每个分支里面都需要有 return

提前return原则
通过提前 return 可以让代码阅读者立刻就鉴别出来程序将在什么情况下 return,同时减少 if else 嵌套,写出更优雅的代码。

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Greeting("Mr.Duan");
  6. }
  7. static void Greeting(string name){
  8. if (string.IsNullOrEmpty(name)){
  9. // 通过尽早 return 可以让代码阅读者立刻就鉴别出来
  10. // name 参数在什么情况下是有问题的
  11. return;
  12. }
  13. Console.WriteLine("Hello, {0}", name);
  14. }
  15. }

using语句→以下展示不讲解

yield语句

lock语句(用于多线程)

checked/unchecked语句(用得不多)

关键字当做语句时的案例 √

标签语句(用得不多)

总是和goto语句一起

空语句(用得不多)