●表达式的定义
evaluate a single value, object, method, or namespace
Single Value 单值
Object 对象
Method 方法
Namespace 命名空间
●各类表达式概览
A Value 一个值
A value. Every value has an associated type. 一个值。每个值都有一个关联的类型。
回顾上一节讲的操作符,并讲解由这些操作符组成的表达式所返回的类型。
条件操作符 ?: 总会返回精度高的那个类型。
A variable 变量
A variable. Every variable has an associated type.一个变量。 每个变量都有一个关联的类型。
A namespace 命名空间
A type 类型
A method group 方法组
Console.WriteLine
,这是一组方法(19 种重载),重载决策决定具体调用那种方法。
A null literal 空值
An anonymous function 匿名方法
A property access 属性访问
An event access 访问时间
An indexer access 访问索引器
Nothing 返回值为void的方法调用
复合表达式的求值
C#语言定义文档里面未明确定义复合表达式,但确实常用。
注意操作符的优先级和同优先级操作符的运算方向(除了赋值操作符,基本都是从左向右)。
参考C#语言定义文档
对于初学者,仅作参考,不必深究 —— 毕竟我们是在学习语言、不是去实现这门语言。
●语句的定义
广义:
实例讲解高级语言与低级语言的差异
狭义:
实例演示控制流
我们的代码没有变,只是执行顺序及分支变了。 尽管语句是固定的,但每次执行的时代,根据输入数据的不同,控制流(执行流)有可能不一样。
●语句详解
嵌入式语句案例:
声明语句
讲解了局部变量声明与局部常量声明,详情参见 C#语言定义文档。
表达式语句
expression-statement 用于计算所给定的表达式。由此表达式计算出来的值(如果有)被丢弃。
Single Responsibility 单一职责原则:一个方法尽量只做一件事情。
下面
x+y
这种语句在 C 语言里面是允许的,在 C# 里面不允许。(无法编译过去)
块语句
● 块语句无论什么时候都被编译器当做一条语句来看待 ● 编译器认为块语句是一条完整的语句(即块语句最后不用加
;
号)Code Snippet
Ctrl + }:跳转至该花括号对应的花括号处。
选择(判断、分支)语句
if 语句
●编程规范推荐即使只有一条语句,也建议使用块语句。为什么?↓
Code Snippet 此处条件只控制了第一行语句 √ (每条语句只能有一条嵌入式语句)
程序员经常修缮前人代码以满足新需求,但因为需求变化(需要实现新逻辑) + 业务逻辑复杂(不敢修改旧代码),导致写出来的代码很臃肿,还很容易陷入思维定式。
无论多长的 if else
,它都是一条语句。之所以能有 else if{}
这种结构,也是因为 if{}
是一条语句。案例如下:
(逐级筛选) 演变成 (else if 语句)
switch 语句
注:从 C# 7.0 开始 switch 表达式已支持任何非 null 表达式
Code Snippet
- Ctrl + L 剪切一整行
Try语句
可以通过 MSDN 查方法相应的异常。
如 Int32.Parse 方法 (String) 就有以下异常。
- 应该把释放系统资源的语句写在 finally block 里面
- 有时候也在 finally block 里面写 log
粗略异常处理 精细异常处理 完整格式
● throw 将异常抛给调用者。(谁调用谁处理)
throw抛出异常案例如下:
● throw 关键字的语法比较灵活。
try{
...
}
catch(OverflowException){
throw;
}
迭代(循环)语句
while语句
- while 语句按不同条件执行一个嵌入语句零次或多次
do语句
- do 语句按不同条件执行一个嵌入语句一次或多次
for语句
- for 语句计算一个初始化表达式序列,然后,当某个条件为真时,重复执行相关的嵌入语句并计算一个迭代表达式序列
执行顺序(重点):左→(中→内部代码→右)→重复括号内部逻辑
for 循环圆括号里面的的三部分都是 opt 可选的(两个分号不能省略),由此可以组成许多平时用不到的奇葩结构。
拓展:遍历和迭代器
① C#所有的数组类型基类都是Array。 ②C#中所有实现了IEnumerable接口的类就是可以被遍历的集合。
Array 实现了 IEnumerable
什么是迭代器?
集合遍历的底层原理和迭代器,foreach 语句就是对集合遍历的简记法。
static void Main(string[] args)
{
var intArray = new int[] { 1, 3, 5 ,7};
IEnumerator enumerator = intArray.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
var intList = new List<int>() { 2, 4, 6, 8 };
IEnumerator enumerator2 = intList.GetEnumerator();
while (enumerator2.MoveNext())
{
Console.WriteLine(enumerator2.Current);
}
}
foreach语句
foreach 语句用于枚举一个集合的元素,并对该集合中的每个元素执行一次相关的嵌入语句
跳转语句
continue语句
continue 语句将开始直接封闭它的 while、do、for 或 foreach 语句的一次新迭代
放弃当前循环,开启新的循环。
break语句
- break 语句将退出直接封闭它的 switch、while、do、for 或 foreach 语句
立刻结束循环,不再进入循环。
goto语句
goto 语句将控制转到由标签标记的语句
throw 语句将引发一个异常
return 语句会将控制返回到出现 return 语句的函数的当前调用方
- 提前 return 原则
- 方法的每个分支里面都需要有 return
提前return原则
通过提前 return 可以让代码阅读者立刻就鉴别出来程序将在什么情况下 return,同时减少 if else 嵌套,写出更优雅的代码。
class Program
{
static void Main(string[] args)
{
Greeting("Mr.Duan");
}
static void Greeting(string name){
if (string.IsNullOrEmpty(name)){
// 通过尽早 return 可以让代码阅读者立刻就鉴别出来
// name 参数在什么情况下是有问题的
return;
}
Console.WriteLine("Hello, {0}", name);
}
}
using语句→以下展示不讲解
yield语句
lock语句(用于多线程)
checked/unchecked语句(用得不多)
关键字当做语句时的案例 √
标签语句(用得不多)
总是和goto语句一起