c# 语句详解.docx
- 文档编号:25958608
- 上传时间:2023-06-16
- 格式:DOCX
- 页数:26
- 大小:29.21KB
c# 语句详解.docx
《c# 语句详解.docx》由会员分享,可在线阅读,更多相关《c# 语句详解.docx(26页珍藏版)》请在冰豆网上搜索。
c#语句详解
8.语句
8.语句
8.1终点与可达性
8.2块
8.2.1语句列表.
8.3空语句.
8.4标号语句.
8.5声明语句
8.5.1局部变量声明.
8.5.2局部常量声明.
8.6表达式语句
8.7选择语句
8.7.1if语句
8.7.2Switch语句
8.8重复语句
8.8.1while语句
8.8.2do语句.
8.8.3for语句
8.8.4foreach语句.
8.9跳转语句
8.9.1break语句.
8.9.2continue语句.
8.9.3goto语句
8.9.4return语句
8.9.5throw语句
8.10try语句
8.11checked和unchecked语句
8.12lock语句.
C#提供各式各样的语句。
当中的绝大部分语句对于那些进行过C和C++编程的人员来讲都很熟悉。
语句:
标号语句声明语句嵌套语句
嵌套语句:
块语句空语句表达式语句选择语句重复iteration语句跳转语句try语句checked语句unchecked语句lock语句
嵌入语句出现在语句的内部。
与通常意义下的语句不同,嵌入语句不允许在其中出现声明声明语句和带标号语句
比如下列代码
voidF(boolb){if(b)inti=44;}
有错误,因为if语句在自身的分支中需要的是嵌入语句而不是通常的语句。
假如允许这样的代码,那么变量i会被声明,但是它并不能被适用。
8.1终点与可达性
每条语句都有终点。
更直观地说,语法上语句书写完成的地方就是该语句的终点。
对于复合语句(嵌套了其他语句)来说,它的执行规则详尽描述了当嵌套语句到达终点时采取的操作。
比如说,当程序执行到一个块中某语句的末尾,那么程序将继续执行块的下一条语句。
如果一条语句可以被执行,那么我们称它为是可达的(reachable)。
相反,如果一条语句无法被执行,我们称之为是不可达的(unreachable)。
下面看一个例子
voidF(){Console.WriteLine("reachable");gotoLabel;Console.WriteLine("unreachable");Label:
Console.WriteLine("reachable");}
第二个Console.WriteLine调用是不可到达的因为这条语句不会被执行。
当便要此段代码时,编译器会发出语句无法到达的警告。
这并不代表语句本身有错使之无法到达。
判断一个语句是否可以到达,编译器是通过按照可达性规则进行流分析而得出结论的。
下面的流分析考虑进来的§错误!
未找到引用源。
节中决定该语句行为的常数表达式的数值,但是非常数表达式的可能值并未被考虑。
换句话说,为了控制流分析,某类型的非常数表达式往往会被认为可以去该类型中的任何值。
请看下面的例子
voidF(){constinti=1;if(i==2)Console.WriteLine("unreachable");}
if语句中的布尔表达式是一个常数表达式因为运算符==的两个操作数都是常数。
该常数表达式在编译是会被取值,它的值为假,因此Console.WriteLine语句对于会被认为是不可到达的。
但是如果变量i变成一个局部变量,如下所示
voidF(){inti=1;if(i==2)Console.WriteLine("reachable");}
Console.WriteLine调用语句将是可以到达的,即使它本身并未被真的执行。
函数子句中的块语句往往总是被认为是可以到达的。
通过依次评估块中的每一条语句,任何语句的可达性都可以被确定。
下面的代码段中
VoidF(intx){Console.WriteLine("start");if(x<0)Console.WriteLine("negative");}
第二个Console.WriteLine语句的可达性是这样确定的:
•首先由于methodF中的块是可以到达的,所有第一个Console.WriteLine语句是可达的。
•其次,由于第一个Console.WriteLine语句是可达的,它的结尾是可达的。
•再次,由于第一个Console.WriteLine语句的结尾是可达的,if语句是可达的。
•最后,由于if语句中的布尔表达式值为真,第二个Console.WriteLine语句是可达的。
有两种情况会使程序语句因为可达性发生错误:
•由于switch语句中不允许任意分支之间发生跳转,所以可能会使该switch语句分支语句在可达性检测时出错。
如果此错误发生,很典型的情况就是缺少break语句。
8.2块
块语句把一系列语句包装成一个语句。
块的一般格式如下:
block:
{statement-listopt}
块语句包括一个可选的如§错误!
未找到引用源。
节中的语句列表,它们被包围在一对花括号中。
假如此语句列表被省略,我们称块为空。
在块当中,某一表达式中出现的某名称含义必须保持一致(详见§7.5.2.1节)。
块是按照下面方式被执行的:
•如果块空,程序跳转到块的结尾。
•如果块非空,程序会依次执行语句列表当中的每一语句。
当程序控制到达语句列表结尾时,它将被转移到块的结尾。
如果块本身是可以到达的,那么块中的语句列表也是可以到达的。
如果块为空或者块中语句列表的结尾可以到达,那么该块的结尾也可到达。
8.2.1语句列表
语句列表包括一系列依次书写的语句。
它可以在会或者switch语句中出现(分别详见§错误!
未找到引用源。
节和§错误!
未找到引用源。
节)。
其一般格式如下:
statement-list:
statementstatement-liststatement
语句列表都是从第一条语句开始执行的。
当执行到该语句的结尾时,程序将会继续执行下一条语句。
当程序执行到列表的最后一条语句时,程序控制也被转移到该列表的结尾。
如果下列所述各项条件中的任意一项满足,语句列表中的语句为可到达的:
•语句为列表中的第一条语句,而且语句列表本身可到达。
•语句列表中的上一语句的结尾可到达。
•当语句为带标号的语句时,标号语句被一条可到达的goto语句引用。
如果语句列表中最后一条语句的结尾是可到达的,那么该列表的结尾也可到达。
8.3空语句
空语句不进行任何操作,其一般格式如下:
empty-statement:
;
在需要语句但又不进行任何操作的时候我们使用空语句。
执行空语句时只需把程序控制转移到语句的结尾。
这样如果空语句是可到达的,那么它的结尾也是可以到达的。
在书写一个空的while语句时,我们可以用到空语句:
boolProcessMessage(){...}
voidProcessMessages(){while(ProcessMessage());}
同样,在块语句的“}”之前,我们可以通过使用一个空语句来声明一个标号:
voidF(){...
if(done)gotoexit;...
exit:
;}
8.4标号语句
标号语句允许一条语句使用标号前缀。
标号语句可以以块的形式出现,但不能以嵌套语句的形式出现。
其格式如下:
labeled-statement:
identifier:
statement
标号语句通过给定一个标识符identifier来声明它的标号。
标号的有效区间为它所在的块内,包括此块的嵌套块。
不允许有两个名字相同的标号的有效区间相互重叠。
标号可以在它的的有效区间内被goto语句引用(详见§错误!
未找到引用源。
节)。
这意味着goto语句可以在块内或由块内到块外完成程序控制的转移,但不能把程序控制转移到子块中。
标号声明有自己的规则,与别的标识符无关。
详见下面的例子
intF(intx){if(x>=0)gotox;x=-x;x:
returnx;}
上面的例程中x作为参数和标号两次出现,这是符合语法规则有效的。
执行一条标号语句时,就是执行标号后面的语句。
另外,除了通常情况下控制流提供的可达性之外,假如一个标号被一条可到达的goto语句引用,那么我们认为此标号语句也是可到达的。
8.5声明语句
声明语句声明一个局部常量或变量。
声明语句可以在块中出现,当是不允许在嵌套语句中出现。
其格式如下:
declaration-statement:
local-variable-declaration;local-constant-declaration;
8.5.1局部变量声明
局部变量声明语句声明一个或多个局部变量。
其格式如下:
local-variable-declaration:
typevariable-declarators
variable-declarators:
variable-declaratorvariable-declarators,variable-declarator
variable-declarator:
identifieridentifier=variable-initializer
variable-initializer:
expressionarray-initializer
被声明的局部变量的类型由声明语句引入的变量类型决定。
在类型之后跟有一个变量声明符清单,其中的每一项都引入一个新的变量。
每个变量声明符包括一个标识符,一个可选的赋值符号“=”以及一个变量初始器,它会给出变量的初始制。
局部变量的值是通过在表达式中使用简单名称获得的(请参见§7.5.2节),局部变量的值可以使用赋值语句修改(参见§错误!
未找到引用源。
节)。
局部变量在每一次取值时必须被明确赋值(参见§错误!
未找到引用源。
节)。
变量的有效区间从它自身的标识符出现开始到它的声明语句所在的块结尾为止。
在局部变量的有效区间内,不能再次声明另外的拥有同样名字的变量或者常量。
在一条局部变量声明语句中声明多个变量等价于多条每次只声明一个同类型局部变量的局部变量声明语句。
不仅如此,变量声明语句中的变量初始器就好像在变量声明语句中插入的一条赋值语句。
请看下面的例子
voidF(){intx=1,y,z=x*2;}
与下面语句完全相当:
voidF(){intx;x=1;inty;intz;z=x*2;}
8.5.2局部常量声明
一个局部常量声明语句声明一个或者多个局部常量。
其格式如下:
local-constant-declaration:
consttypeconstant-declarators
constant-declarators:
constant-declaratorconstant-declarators,constant-declarator
constant-declarator:
identifier=constant-expression
被声明的局部常量的类型由声明语句引入的常量类型决定。
在类型之后跟有一个常量声明符清单,其中的每一项都引入一个新的常量。
每个常量声明符包括一个标识符,一个赋值符号“=”以及一个给出常量数值的常量表达式(参见§错误!
未找到引用源。
节)。
局部常量声明语句中的类型和常数表达式必须遵从有关常量成分声明的规则(参见§10.3节)。
局部常量的值是通过在表达式中使用简单名称获得的(请参见§7.5.2节)。
常量的有效区间从声明开始到它的声明语句所在的块结尾为止。
在局部常量的有效区间内,不能再次声明另外的拥有同样名字的变量或者常量。
8.6表达式语句
表达式语句对列出的表达式求值。
又表达式计算出的数值,无论多少都被丢弃。
其格式如下:
expression-statement:
statement-expression;
statement-expression:
invocation-expressionobject-creation-expressionassignmentpost-increment-expressionpost-decrement-expressionpre-increment-expressionpre-decrement-expression
并不是所有表达式都允许以语句的形式出现。
尤其是象x+y和x==1这样的没有side-effect的表达式,它们只是用来求值。
表达式语句计算它列出的表达式的值,之后将程序的控制转移到表达式语句的末尾。
8.7选择语句
选择语句依据一个控制表达式的计算值从一系列可能被执行的语句选择出要执行的语句。
其格式如下:
选择语句:
if语句switch语句
8.7.1if语句
if语句依据括号中的布尔表达式选择相关语句执行。
其格式如下:
if-statement:
if(boolean-expression)embedded-statementif(boolean-expression)embedded-statementelseembedded-statement
boolean-expression:
expression
else分支与最近的if语句构成一个if-else对。
If语句并不一定必须有else分支。
这样如下所示的if语句
if(x)if(y)F();elseG();
等价于下面的语句
if(x){if(y){F();}else{G();}}
if语句按照下面的方式执行:
•求布尔表达式的值(参见§错误!
未找到引用源。
节)。
•如果布尔表达式为真,程序将跳转到分语句的第一个嵌套语句执行。
当程序执行到此嵌套语句的结尾,程序控制将转移到if语句的结尾。
•如果布尔表达式的值为假,而且分语句中有else分支,程序跳转到分语句的第二个嵌套语句执行。
当程序执行到此嵌套语句的结尾时,程序控制将转移到if语句的结尾。
•如果布尔表达式的值为假,而且分语句中没有else分支,程序控制将转移到if语句的结尾。
假如if语句本身可到达而且它的布尔表达式值为真,那么if语句的第一个嵌套语句可到达。
假如if语句本身可到达而且它有第二个嵌套语句并且它的布尔表达式值为假,那么if语句的第二个嵌套语句可到达。
假如if语句的任意一个嵌套语句的结尾可到达,那么if语句的结尾也可到达。
另外,假如一个没有elso分支的if语句本身可到达而且它的布尔表达式值为假,那么if语句的结尾可到达。
8.7.2Switch语句
switch-statement:
switch(expression)switch-block
switch-block:
{switch-sectionsopt}
switch-sections:
switch-sectionswitch-sectionsswitch-section
switch-section:
switch-labelsstatement-list
switch-labels:
switch-labelswitch-labelsswitch-label
switch-label:
caseconstant-expression:
default:
switch语句包括关键字switch和其后的括号表达式(我们称之为switch表达式)和switch块。
Switch块包含有零个或者多个由括号包围的switch分支。
每个switch分支又由一个或者多个switch标号和跟在它们后面的语句列表组成。
Switch语句的控制类型由switch表达式决定。
如果switch表达式的类型为sbyte,byte,short,ushort,int,uint,long,ulong,char,string或者枚举型,那么这就是switch语句的控制类型。
否则,必须有一个用户自定义隐式转换语句(参见§错误!
未找到引用源。
节)把switch表达式的类型转换为下述控制类型类型中的一种:
Sbyte,byte,short,ushort,int,int,long,ulong,char,string。
如果没有这样的一条转换语句或者有多条这样的转换语句存在,将产生编译错误。
每一个switch分支的常数表达式必须取得某个可被隐式转换成switch语句控制类型的数值。
如果同一个switch有两个或两个以上的switch分支的常量表达式取得相同的值,那么编译时会出错。
每一个switch语句最多只能有一个default标号分支。
Switch语句时按照如下方式执行的:
•首先计算出switch表达式的值并转换到控制类型。
•如果swtich表达式的值等于某一个switch分支的常量表达式的值,那么程序控制跳转到这个case标号后的语句列表中。
•如果switch表达式的值无法与switch语句中任何一个case常量表达式的值匹配而且switch语句中有default分支,程序控制会跳转到default标号后的语句列表中。
•如果switch表达式的值无法与switch语句中任何一个case常量表达式的值匹配而且switch语句中没有default分支,程序控制会跳转到switch语句的结尾。
如果一个switch语句的语句列表决定结尾是可到达的,将会产生编译错误。
这就是我们所说的“无失败(nofallthrough)”规则。
请看下面的例子
switch(i){case0:
CaseZero();break;case1:
CaseOne();break;default:
CaseOthers();break;}
此switch语句是正确有效的,因为没有任意switch分支的结尾是可达的。
与C和C++不同,程序控制不能在相邻switch分支中转移,请看下面的例子
switch(i){case0:
CaseZero();case1:
CaseZeroOrOne();default:
CaseAny();}
这个switch语句是错误的。
当程序要在不同的switch分支间跳转时必须在跳离的switch分支中加入gotocase语句或者gotodefault语句.请看下面的例子:
switch(i){case0:
CaseZero();gotocase1;case1:
CaseZeroOrOne();gotodefault;default:
CaseAny();break;}
switch语句可以有多个switch分支,如下面例程所示。
switch(i){case0:
CaseZero();break;case1:
CaseOne();break;case2:
default:
CaseTwo();break;}
这个switch语句时合法的。
此例子并未违背“nofallthrough”规则因为在case2分支和default分支属于switch语句中的同一个分支。
“无失败”规则可以防止象C和C++语言中的break语言被忽略的常见错误。
同样因为这个规则,可以在不影响switch语句功能的情况下重重新排列其中的switch分支。
如同下面的例程中,即使我们调换几个switch分支的顺序,整个switch语句的功能没有丝毫变化。
switch(i){default:
CaseAny();break;case1:
CaseZeroOrOne();gotodefault;case0:
CaseZero();gotocase1;}
典型switch分支的语句列表往往是以break或gotocase或者gotodefault语句作为结尾,但是也有可能某些结构使得这些语句列表的结尾无法到达。
比如,布尔表达式恒为真的while循环语句就永远无法执行到它的结尾。
同样,throw或return语句总是跳转程序控制而无法执行到自身的结尾。
下面的switch语句是正确的。
switch(i){case0:
while(true)F();case1:
thrownewArgumentException();case2:
return;}
一个switch语句的控制类型可以是字符串类型的,如下面例程所示:
voidDoCommand(stringcommand){switch(command.ToLower()){case"run":
DoRun();break;case"save":
DoSave();break;case"quit":
DoQuit();break;default:
InvalidCommand(command);break;}}
就像§错误!
未找到引用源。
节中的字符串相等操作符,switch语句是区分大小写的,只有switch表达式的值与case分支常数的值完全匹配,此case标号后的语句才会被执行。
正如上面的例子所示,可以通过把switch表达式字符串和case分支常量都转换为小写的方法把此switch语句变成大小写区分的。
当一个switch语句的控制类型为字符串类型时,null可以作为case分支常量。
Switch会可以包含有声明语句(参见§错误!
未找到引用源。
节)。
Switch块中局部变量和常量的有效区间从它们被声明开始到switch块结束为止。
在switch块中,表达式中使用的使用的名字的含义必须始终保持一致(参见§7.5.2.1节)。
如果switch语句是可到达的而且下面各项中的一项或多项被满足,那么某一switch分支的语句列表也是可到达的:
•switch表达式为非常数值.
•Switch表达式的值为常数且等于该switch分支的case标号常量。
•Switch表达式的值为常量但不等于任何一个switch分支的case标号常量,而且此switch语句含义default分支标号分支。
•某个switch标号被一条可到达的gotocase或gotodefault语句引用
如果满足下列各项中的一项,则我们认为switch语句的结尾是可以到达的:
•switch语句包含有一条可到达的跳出switch语句的break语句。
•switch语句可到达且switch表达式的值为非常量并且switch语句中不含有default分支。
•switch语句可到达且switch表达式的值为常量但不与语句中的任一case标号常量匹配并且switch语句中不含有default分支。
8.8重复语句
重复语句反复执行某一嵌套语句。
重复语句:
while语句do语句for语句foreach语句
8.8.1while语句
while依据其表达式的值条件执行它的嵌套语句零次或者多次。
其格式如下:
while-statement:
while(boolean-e
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- c# 语句详解 语句 详解