表达式的定义
- 什么是表达式(其他语言对表达式的定义)
- C#语言对表达式的定义
示例:
static void Main(string[] args)
{
int x;
x = 100;//赋值表达式,得到的结果是一个single value。
new Form();//new表达式,操作符为new,操作数为Form类型,得到的结果是一个对象object
Action action = new Action(Console.WriteLine);
//Console.WriteLine是成员访问表达式,操作符为".",操作数为Console类型和WriteLine类型成员
//得到的结果是一个方法method
System.Windows.Forms.Form myForm = new Form();
//System.Windows是名称空间访问表达式,操作符为".",操作数System主名称空间,Windows是子名称空间
//得到的结果是一个名称空间
int y;
y = 5;//5是一个字面值,参与构成表达式
double a = Math.Pow(2, 3);//Math.Pow(2, 3)是一个函数调用,也是一个表达式
int z = 2 + 6;// 2 + 6是由操作符和操作数构成的一个表达式
int b = 100, c;
c = b;//b是一个变量名simple name,参与构成表达式
}
各类表达式概览
- C#语言中表达式的分类
- 复合表达式的求值
- 由多个小表达式组成
- 注意操作符的优先级和同优先级操作符的运算方向
- 参考C#语言定义文档(第7章)
- 仅做参考,不必深究——我们是在学习语言,不是去实现这门语言
语句的定义
- Wikipedia对语句的定义
- 查看C#编译好后的低级语言代码:
- 在win下打开developer command prompt for vs 2019,
- 在窗口写入ildasm
- 在弹出的界面,文件中打开C#debug下的应用程序文件
- 双击方法即可查看低级语言代码
- 如下图
- C#语言对语句的定义
- 示例:
```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#语言规范》文档的定义:
- 示例:
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#语言规范》文档的定义:
- 常配合选择语句、循环语句等一起使用,单独使用较少,且内部变量是有作用域的
- 示例: ```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#语言规范》文档的定义:
示例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语句格式如下:
示例:有一个算术运算的小游戏,当输出两个值的和为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语句格式如下:
示例:将以上代码用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语句格式:
示例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语句格式:
- 所有实现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语句格式如下:
示例: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语句格式如下:
示例:还是前面的算术小游戏,新增功能,当小朋友想结束游戏,又不想估计输错数值,使用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语句格式如下:
throw语句
- throw语句引发一个异常(前面有示例)
- throw语句灵活多变,后面可不跟参数
- throw语句格式如下: