首页 C#变量5

C#变量5

举报
开通vip

C#变量5变量 81 5.1 变量类别 81 5.1.1 静态变量 81 5.1.2 实例变量 81 5.1.2.1 类中的实例变量 81 5.1.2.2 结构中的实例变量 82 5.1.3 数组元素 82 5.1.4 值参数 82 5.1.5 引用参数 82 5.1.6 输出参数 82 5.1.7 局部变量 83 5.2 默认值 83 5.3 明确赋值 84 5.3.1 初始已赋值变量 84 5.3.2 初始未赋值变量 85 5.3.3 确定明确赋值的细则 85 5.3.3.1 一般语句规则 85 5.3.3.2 块语句、...

C#变量5
变量 81 5.1 变量类别 81 5.1.1 静态变量 81 5.1.2 实例变量 81 5.1.2.1 类中的实例变量 81 5.1.2.2 结构中的实例变量 82 5.1.3 数组元素 82 5.1.4 值参数 82 5.1.5 引用参数 82 5.1.6 输出参数 82 5.1.7 局部变量 83 5.2 默认值 83 5.3 明确赋值 84 5.3.1 初始已赋值变量 84 5.3.2 初始未赋值变量 85 5.3.3 确定明确赋值的细则 85 5.3.3.1 一般语句规则 85 5.3.3.2 块语句、checked 和 unchecked 语句 86 5.3.3.3 表达式语句 86 5.3.3.4 声明语句 86 5.3.3.5 if 语句 86 5.3.3.6 switch 语句 87 5.3.3.7 while 语句 87 5.3.3.8 do 语句 87 5.3.3.9 for 语句 87 5.3.3.10 break、continue 和 goto 语句 88 5.3.3.11 throw 语句 88 5.3.3.12 return 语句 88 5.3.3.13 try-catch 语句 88 5.3.3.14 try-finally 语句 88 5.3.3.15 try-catch-finally 语句 89 5.3.3.16 foreach 语句 90 5.3.3.17 using 语句 90 5.3.3.18 lock 语句 90 5.3.3.19 简单表达式的一般规则 90 5.3.3.20 带有嵌入表达式的表达式的一般规则 91 5.3.3.21 调用表达式和对象创建表达式 91 5.3.3.22 简单赋值表达式 91 5.3.3.23 && 表达式 92 5.3.3.24 || 表达式 92 5.3.3.25 ! 表达式 93 5.3.3.26 ?: 表达式 93 5.4 变量引用 94 5.5 变量引用的原子性 94 1.变量 变量表示存储位置。每个变量都具有一个类型,它确定哪些值可以存储在该变量中。C# 是一种类型安全的语言,C# 编译器保证存储在变量中的值总是具有合适的类型。通过赋值或使用 ++ 和 -- 运算符可以更改变量的值。 在可以获取变量的值之前,变量必须已明确赋值 (definitely assigned)(第 5.3 节)。 如下面的章节所述,变量是初始已赋值 (initially assigned) 或初始未赋值 (initially unassigned)。初始已赋值的变量有一个正确定义了的初始值,并且总是被视为已明确赋值。初始未赋值的变量没有初始值。为了使初始未赋值的变量在某个位置被视为已明确赋值,变量赋值必须发生在通向该位置的每个可能的执行路径中。 1.1变量类别 C# 定义了 7 种变量类别:静态变量、实例变量、数组元素、值参数、引用参数、输出参数和局部变量。后面的章节将介绍其中的每一种类别。 在下面的示例中 class A { public static int x; int y; void F(int[] v, int a, ref int b, out int c) { int i = 1; c = a + b++; } } x 是静态变量,y 是实例变量,v[0] 是数组元素,a 是值参数,b 是引用参数,c 是输出参数,i 是局部变量。 1.1.1静态变量 用 static 修饰符声明的字段称为静态变量 (static variable)。静态变量在包含了它的那个类型的静态构造函数(第 10.11 节)执行之前就存在了,在关联的应用程序域终止时终止。 静态变量的初始值是该变量的类型的默认值(第 5.2 节)。 出于明确赋值检查的目的,静态变量被视为初始已赋值。 1.1.2实例变量 未用 static 修饰符声明的字段称为实例变量 (instance variable)。 1.1.2.1类中的实例变量 类的实例变量在创建该类的新实例时开始存在,在所有对该实例的引用都已终止,并且已执行了该实例的析构函数(若有)时终止。 类实例变量的初始值是该变量的类型的默认值(第 5.2 节)。 出于明确赋值检查的目的,类的实例变量被视为初始已赋值。 1.1.2.2结构中的实例变量 结构的实例变量与它所属的结构变量具有完全相同的生存期。换言之,当结构类型的变量开始存在或停止存在时,该结构的实例变量也随之存在或消失。 结构的实例变量与包含它的结构变量具有相同的初始赋值状态。换言之,当结构变量本身被视为初始已赋值时,它的实例变量也被视为初始已赋值。而当结构变量被视为初始未赋值时,它的实例变量同样被视为未赋值。 1.1.3数组元素 数组的元素在创建数组实例时开始存在,在没有对该数组实例的引用时停止存在。 每个数组元素的初始值都是其数组元素类型的默认值(第 5.2 节)。 出于明确赋值检查的目的,数组元素被视为初始已赋值。 1.1.4值参数 未用 ref 或 out 修饰符声明的参数为值参数 (value parameter)。 值形参在调用该参数所属的函数成员(方法、实例构造函数、访问器或运算符)时开始存在,并用调用中给定的实参的值初始化。当返回该函数成员时值参数停止存在。 出于明确赋值检查的目的,值参数被视为初始已赋值。 1.1.5引用参数 用 ref 修饰符声明的参数是引用参数 (reference parameter)。 引用参数不创建新的存储位置。相反,引用参数表示的是那个在对该函数成员调用中被当作“自变量”的变量所表示的同一个存储位置。因此,引用参数的值总是与基础变量相同。 下面的明确赋值规则适用于引用参数。注意第 5.1.6 节中描述的输出参数的不同规则。 ​ 变量在可以作为引用参数在函数成员调用中传递之前,必须已明确赋值(第 5.3 节)。 ​ 在函数成员内部,引用参数被视为初始已赋值。 在结构类型的实例方法或实例访问器内部,this 关键字的行为与该结构类型的引用参数完全相同(第 7.5.7 节)。 1.1.6输出参数 用 out 修饰符声明的参数是输出参数 (output parameter)。 输出参数不创建新的存储位置。相反,输出参数表示的是那个在对该函数成员调用中被当作“自变量”的变量所表示的同一个存储位置。因此,输出参数的值总是与基础变量相同。 下面的明确赋值规则应用于输出参数。注意第 5.1.5 节中描述的引用参数的不同规则。 ​ 变量在可以作为输出参数在函数成员调用中传递之前不一定要明确赋值。 ​ 在正常完成函数成员调用之后,每个作为输出参数传递的变量都被认为在该执行路径中已赋值。 ​ 在函数成员内部,输出参数被视为初始未赋值。 ​ 函数成员的每个输出参数在该函数成员正常返回前都必须已明确赋值(第 5.3 节)。 在结构类型的实例构造函数内部,this 关键字的行为与结构类型的输出参数完全相同(第 7.5.7 节)。 1.1.7局部变量 局部变量 (local variable) 是通过 local-variable-declaration 来声明的,此声明可以出现在 block、for-statement、switch-statement 或 using-statement 中。 局部变量的生存期是程序执行过程中的某一“段”,在此期间,一定会为该局部变量保留存储。此生存期从进入与它关联的 block、for-statement、switch-statement 或 using-statement 开始,一直延续到对应的 block、for-statement、switch-statement 或 using-statement 的执行以任何方式结束为止。(进入封闭 block 或调用方法会挂起(但不会结束)当前的 block、for-statement、switch-statement 或 using-statement 的执行。)如果以递归方式进入父 block、for-statement、switch-statement 或 using-statement,则每次都创建局部变量的新实例,并且重新计算它的 local-variable-initializer(如果有)。 局部变量不自动初始化,因此没有默认值。出于明确赋值检查的目的,局部变量被视为初始未赋值。local-variable-declaration 可包括 local-variable-initializer,在此情况下变量被视为在它的整个范围内(local-variable-initializer 中提供的表达式内除外)已明确赋值。 在局部变量的范围内,在 local-variable-declarator 之前的文本位置引用该局部变量是编译时错误。 局部变量的实际生存期依赖于具体实现。例如,编译器可能静态地确定块中的某个局部变量只用于该块的一小部分。使用这种分析,编译器生成的代码可能会使该变量存储的生存期短于包含该变量的块的生存期。 局部引用变量所引用的存储的回收与该局部引用变量(第 3.9 节)的生存期无关。 foreach-statement 和 try-statement 的 specific-catch-clause 也声明局部变量。对于 foreach-statement,局部变量是一个迭代变量(第 8.8.4 节)。对于 specific-catch-clause,局部变量是一个异常变量(第 8.10 节)。foreach-statement 或 specific-catch-clause 所声明的局部变量被视为在它的整个范围内已明确赋值。 1.2默认值 以下类别的变量自动初始化为它们的默认值: ​ 静态变量。 ​ 类实例的实例变量。 ​ 数组元素。 变量的默认值取决于该变量的类型,并按下面这样确定: ​ 对于 value-type 的变量,默认值与该 value-type 的默认构造函数(第 0 章)所计算的值相同。 ​ 对于 reference-type 的变量,默认值为 null。 初始化为默认值的实现方法一般是让内存管理器或垃圾回收器在分配内存以供使用之前,将内存初始化为“所有位归零”(all-bits-zero)。由于这个原因,使用所有位归零来表示空 (null) 引用很方便。 1.3明确赋值 在函数成员可执行代码中的给定位置,如果编译器可通过特定的静态 流程 快递问题件怎么处理流程河南自建厂房流程下载关于规范招聘需求审批流程制作流程表下载邮件下载流程设计 分析(第 5.3.3 节)证明变量已自动初始化或已成为至少一个赋值的目标,则称该变量已明确赋值 (definitely assigned)。非正式地讲,明确赋值的规则为: ​ 初始已赋值的变量(第 5.3.1 节)总是被视为已明确赋值。 ​ 如果所有可能通向给定位置的执行路径都至少包含以下 内容 财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容 之一,则初始未赋值的变量(第 5.3.2 节)被视为在该位置已明确赋值: o​ 将变量作为左操作数的简单赋值(第 7.13.1 节)。 o​ 将变量作为输出参数传递的调用表达式(第 7.5.5 节)或对象创建表达式(第 7.5.10.1 节)。 o​ 对于局部变量,包含变量初始值设定项的局部变量声明(第 8.5 节)。 以上非正式规则所基于的正式 规范 编程规范下载gsp规范下载钢格栅规范下载警徽规范下载建设厅规范下载 在第 5.3.1 节、第 5.3.2 节和第 5.3.3 节中说明。 关于对一个 struct-type 变量的实例变量是否明确赋值,既可个别地也可作为整体进行跟踪。除了上述规则,下面的规则也应用于 struct-type 变量及其实例变量: ​ 如果一个实例变量的包含它的那个 struct-type 变量被视为已明确赋值,则该实例变量被视为已明确赋值。 ​ 如果一个 struct-type 变量的每个实例变量都被视为已明确赋值,则该结构类型变量被视为已明确赋值。 在下列上下文中要求实施明确赋值: ​ 变量必须在获取其值的每个位置都已明确赋值。这确保了从来不会出现未定义的值。变量在表达式中出现被视为要获取该变量的值,除非当 o​ 该变量为简单赋值的左操作数, o​ 该变量作为输出参数传递,或者 o​ 该变量为 struct-type 变量并作为成员访问的左操作数出现。 ​ 变量必须在它作为引用参数传递的每个位置都已明确赋值。这确保了被调用的函数成员可以将引用参数视为初始已赋值。 ​ 函数成员的所有输出参数必须在函数成员返回的每个位置都已明确赋值,返回位置包括通过 return 语句实现的返回,或者通过执行语句到达函数成员体结尾的返回。这确保了函数成员不在输出参数中返回未定义的值,从而使编译器能够把一个对函数成员的调用当作对某些变量的赋值,这些变量在该调用中被当作输出参数传递。 ​ struct-type 实例构造函数的 this 变量必须在该实例构造函数返回的每个位置明确赋值。 1.3.1初始已赋值变量 以下类别的变量属于初始已赋值变量: ​ 静态变量。 ​ 类实例的实例变量。 ​ 初始已赋值结构变量的实例变量。 ​ 数组元素。 ​ 值参数。 ​ 引用参数。 ​ 在 catch 子句或 foreach 语句中声明的变量。 1.3.2初始未赋值变量 以下类别的变量属于初始未赋值变量: ​ 初始未赋值结构变量的实例变量。 ​ 输出参数,包括结构实例构造函数的 this 变量。 ​ 局部变量,在 catch 子句或 foreach 语句中声明的那些除外。 1.3.3确定明确赋值的细则 为了确定每个已使用变量都已明确赋值,编译器必须使用与本节中描述的进程等效的进程。 编译器处理每个具有一个或多个初始未赋值变量的函数成员的体。对于每个初始未赋值的变量 v,编译器在函数成员中的下列每个点上确定 v 的明确赋值状态 (definite assignment state): ​ 在每个语句的开头处 ​ 在每个语句的结束点(第 8.1 节) ​ 在每个将控制转移到另一个语句或语句结束点的 arc 上 ​ 在每个表达式的开头处 ​ 在每个表达式的结尾处 v 的明确赋值状态可以是: ​ 明确赋值。这表明在能达到该点的所有可能的控制流上,v 都已赋值。 ​ 未明确赋值。当在 bool 类型表达式结尾处确定变量的状态时,未明确赋值的变量的状态可能(但不一定)属于下列子状态: o​ 在 true 表达式后明确赋值。此状态表明如果该布尔表达式计算为 true,则 v 是明确赋值的,但如果布尔表达式计算为 false,则不一定要赋值。 o​ 在 false 表达式后明确赋值。此状态表明如果该布尔表达式计算为 false,则 v 是明确赋值的,但如果布尔表达式计算为 true,则不一定要赋值。 下列规则控制变量 v 的状态在每个位置是如何确定的。 1.3.3.1一般语句规则 ​ v 在函数成员体的开头处不是明确赋值的。 ​ v 在任何无法访问的语句的开头处都是明确赋值的。 ​ 在任何其他语句开头处,为了确定 v 的明确赋值状态,请检查以该语句开头处为目标的所有控制流转移上的 v 的明确赋值状态。当且仅当 v 在所有此类控制流转移上是明确赋值的时,v才在该语句的开始处明确赋值。确定可能的控制流转移集的方法与检查语句可访问性的方法(第 8.1 节)相同。 ​ 在 block、checked、unchecked、if、while、do、for、foreach、lock、using 或 switch 等语句的结束点处,为了确定 v 的明确赋值状态,需检查以该语句结束点为目标的所有控制流转移上的 v 的明确赋值状态。如果 v 在所有此类控制流转移上是明确赋值的,则 v 在该语句结束点明确赋值。否则,v 在语句结束点处不是明确赋值的。确定可能的控制流转移集的方法与检查语句可访问性的方法(第 8.1 节)相同。 1.3.3.2块语句、checked 和 unchecked 语句 在指向位于某块中语句列表的第一个语句(如果语句列表为空,则指向该块的结束点)的控制转移上,v 的明确赋值状态与块语句、checked 或 unchecked 语句之前的 v 的明确赋值状态相同。 1.3.3.3表达式语句 对于由表达式 expr 组成的表达式语句 stmt: ​ v 在 expr 的开头处与在 stmt 的开头处具有相同的明确赋值状态。 ​ 如果 v 在 expr 的结尾处明确赋值,则它在 stmt 的结束点也明确赋值;否则,它在 stmt 的结束点也不明确赋值。 1.3.3.4声明语句 ​ 如果 stmt 是不带有初始值设定项的声明语句,则 v 在 stmt 的结束点与在 stmt 的开头处具有相同的明确赋值状态。 ​ 如果 stmt 是带有初始值设定项的声明语句,则确定 v 的明确赋值状态时可把 stmt 当作一个语句列表,其中每个带有初始值设定项的声明对应一个赋值语句(按声明的顺序)。 1.3.3.5if 语句 对于具有以下形式的 if 语句 stmt: if ( expr ) then-stmt else else-stmt ​ v 在 expr 的开头处与在 stmt 的开头处具有相同的明确赋值状态。 ​ 如果 v 在 expr 的结尾处明确赋值,则它在指向 then-stmt 和 else-stmt 或指向 stmt 的结束点(如果没有 else 子句)的控制流转移上是明确赋值的。 ​ 如果 v 在 expr 的结尾处具有“在 true 表达式后明确赋值”状态,则它在指向 then-stmt 的控制流转移上是明确赋值的,在指向 else-stmt 或指向 stmt 的结束点(如果没有 else 子句)的控制流转移上不是明确赋值的。 ​ 如果 v 在 expr 的结尾处具有“在 false 表达式后明确赋值”状态,则它在指向 else-stmt 的控制流转移上是明确赋值的,在指向 then-stmt 的控制流转移上不是明确赋值的。此后,当且仅当它在 then-stmt 的结束点是明确赋值的时,它在 stmt 的结束点才是明确赋值的。 ​ 否则,认为 v 在指向 then-stmt 或 else-stmt,或指向 stmt 的结束点(如果没有 else 子句)的控制流转移上都不是明确赋值的。 1.3.3.6switch 语句 在带有控制表达式 expr 的 switch 语句 stmt 中: ​ 位于 expr 开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 ​ 在指向可访问的 switch 块语句列表的控制流转移上,v 的明确赋值状态就是它在 expr 结尾处的明确赋值状态。 1.3.3.7while 语句 对于具有以下形式的 while 语句 stmt: while ( expr ) while-body ​ v 在 expr 的开头处与在 stmt 的开头处具有相同的明确赋值状态。 ​ 如果 v 在 expr 的结尾处明确赋值,则它在指向 while-body 和指向 stmt 结束点的控制流转移上是明确赋值的。 ​ 如果 v 在 expr 的结尾处具有“在 true 表达式后明确赋值”状态,则它在指向 while-body 的控制流转移上是明确赋值的,但在 stmt 的结束点处不是明确赋值的。 ​ 如果 v 在 expr 的结尾处具有“在 false 表达式后明确赋值”状态,则它在指向 stmt 的结束点的控制流转移上是明确赋值的,但在指向 while-body 的控制流转移上不是明确赋值的。 1.3.3.8do 语句 对于具有以下形式的 do 语句 stmt: do do-body while ( expr ) ; ​ v 在从 stmt 的开头处到 do-body 的控制流转移上的明确赋值状态与在 stmt 的开头处的状态相同。 ​ v 在 expr 的开头处与在 do-body 的结束点具有相同的明确赋值状态。 ​ 如果 v 在 expr 的结尾处是明确赋值的,则它在指向 stmt 的结束点的控制流转移上是明确赋值的。 ​ 如果 v 在 expr 的结尾处的状态为“在 false 表达式后明确赋值”,则它在指向 stmt 的结束点的控制流转移上是明确赋值的。 1.3.3.9for 语句 对具有以下形式的 for 语句进行的明确赋值检查: for ( for-initializer ; for-condition ; for-iterator ) embedded-statement 就如执行下列语句一样: { for-initializer ; while ( for-condition ) { embedded-statement ; for-iterator ; } } 如果 for 语句中省略了 for-condition,则在确定关于明确赋值的状态时,可把上述展开语句列表中的 for-condition 当作 true。 1.3.3.10break、continue 和 goto 语句 由 break、continue 或 goto 语句引起的控制流转移上的 v 的明确赋值状态与它在该语句开头处的明确赋值状态是一样的。 1.3.3.11throw 语句 对于具有以下形式的语句 stmt throw expr ; 位于 expr 开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 1.3.3.12return 语句 对于具有以下形式的语句 stmt return expr ; ​ 位于 expr 开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 ​ 如果 v 是输出参数,则它必须在下列两个位置之一被明确赋值: o​ 在 expr 之后 o​ 在包含 return 语句的 try-finally 或 try-catch-finally 的 finally 块的结尾处。 对于具有以下形式的语句 stmt: return ; ​ 如果 v 是输出参数,则它必须在下列两个位置之一被明确赋值: o​ 在 stmt 之前 o​ 在包含 return 语句的 try-finally 或 try-catch-finally 的 finally 块的结尾处。 1.3.3.13try-catch 语句 对于具有以下形式的语句 stmt: try try-block catch(...) catch-block-1 ... catch(...) catch-block-n ​ 位于 try-block 开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 ​ 位于 catch-block-i(对于所有的 i)开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 ​ 当且仅当 v 在 try-block 和每个 catch-block-i(每个 i 从 1 到 n)的结束点明确赋值时,stmt 结束点处的 v 的明确赋值状态才是明确赋值的。 1.3.3.14try-finally 语句 对于具有以下形式的 try 语句 stmt: try try-block finally finally-block ​ 位于 try-block 开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 ​ 位于 finally-block 开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 ​ 当且仅当下列条件中至少有一个为真时,位于 stmt 结束点处的 v 的明确赋值状态才是明确赋值的: o​ v 在 try-block 的结束点明确赋值 o​ v 在 finally-block 的结束点明确赋值 如果控制流转移(例如,goto 语句)从 try-block 内开始,在 try-block 外结束,那么如果 v 在 finally-block 的结束点明确赋值,v 也被认为在该控制流转移上明确赋值。(这不是必要条件,如果 v 由于其他原因在该控制流转移上明确赋值,则它仍被视为明确赋值。) 1.3.3.15try-catch-finally 语句 对具有以下形式的 try-catch-finally 语句进行的明确赋值分析: try try-block catch(...) catch-block-1 ... catch(...) catch-block-n finally finally-block 在进行明确赋值分析时,可把该语句当作包含了 try-catch 语句的 try-finally 语句,如下所示: try { try try-block catch(...) catch-block-1 ... catch(...) catch-block-n } finally finally-block 下面的示例演示 try 语句(第 8.10 节)的不同块如何影响明确赋值状态。 XE "assignment:definite:try and" \b class A { static void F() { int i, j; try { goto LABEL; // neither i nor j definitely assigned i = 1; // i definitely assigned } catch { // neither i nor j definitely assigned i = 3; // i definitely assigned } finally { // neither i nor j definitely assigned j = 5; // j definitely assigned } // i and j definitely assigned LABEL:; // j definitely assigned } } 1.3.3.16foreach 语句 对于具有以下形式的 foreach 语句 stmt: foreach ( type identifier in expr ) embedded-statement ​ 位于 expr 开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 ​ 在指向 embedded-statement 或指向 stmt 结束点处的控制流转移上,v 的明确赋值状态与位于 expr 结尾处的 v 的状态相同。 1.3.3.17using 语句 对于具有以下形式的 using 语句 stmt: using ( resource-acquisition ) embedded-statement ​ 位于 resource-acquisition 开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 ​ 在指向 embedded-statement 的控制流转移上,v 的明确赋值状态与位于 resource-acquisition 结尾处的 v 的状态相同。 1.3.3.18lock 语句 对于具有以下形式的 lock 语句 stmt: lock ( expr ) embedded-statement ​ 位于 expr 开头处的 v 的明确赋值状态与位于 stmt 开头处的 v 的明确赋值状态相同。 ​ 在指向 embedded-statement 的控制流转移上,v 的明确赋值状态与位于 expr 结尾处的 v 的状态相同。 1.3.3.19简单表达式的一般规则 下列规则应用于这些类型的表达式:文本(第 7.5.1 节)、简单名称(第 7.5.2 节)、成员访问表达式(第 7.5.4 节)、非索引 base 访问表达式(第 7.5.8 节)和 typeof 表达式(第 7.5.11 节)。 ​ 位于此类表达式结尾处的 v的明确赋值状态与位于表达式开头处的 v 的明确赋值状态相同。 1.3.3.20带有嵌入表达式的表达式的一般规则 下列规则应用于这些类型的表达式:带括号的表达式(第 7.5.3 节);元素访问表达式(第 7.5.6 节);带索引的 base 访问表达式(第 7.5.8 节);增量和减量表达式(第 7.5.9 节、第 7.6.5 节);强制转换表达式(第 7.6.6 节);一元 +、-、~、* 表达式;二元 +、-、*、/、%、<<、>>、<、<=、>、>=、==、!=、is、as、&、|、^ 表达式(第 7.7 节、第 7.8 节、第 7.9 节、第 7.10 节);复合赋值表达式(第 7.13.2 节);checked 和 unchecked 表达式(第 7.5.12 节);数组和委托创建表达式(第 7.5.10 节)。 这些表达式的每一个都有一个和多个按固定顺序无条件计算的子表达式。例如,二元运算符 % 先计算运算符左边的值,然后计算右边的值。索引操作先计算索引表达式,然后按从左到右的顺序计算每个索引表达式。对于具有子表达式 expr1、expr2、...、exprn 的表达式 expr,按下列顺序计算: ​ 位于 expr1 开头处的 v 的明确赋值状态与位于 expr 开头处的 v 的明确赋值状态相同。 ​ 位于 expri(i 大于 1)开头处的 v 的明确赋值状态与位于 expri-1 结尾处的 v 的明确赋值状态相同。 ​ 位于 expr 结尾处的 v 的明确赋值状态与位于 exprn 结尾处的 v 的明确赋值状态相同。 1.3.3.21调用表达式和对象创建表达式 对于具有以下形式的调用表达式 expr: primary-expression ( arg1 , arg2 , … , argn ) 或具有以下形式的对象创建表达式: new type ( arg1 , arg2 , … , argn ) ​ 对于调用表达式,位于 primary-expression 之前的 v 的明确赋值状态与位于 expr 之前的 v 的状态相同。 ​ 对于调用表达式,位于 arg1 之前的 v 的明确赋值状态与位于 primary-expression 之后的 v 的明确赋值状态相同。 ​ 对于对象创建表达式,位于 arg1 之前的 v 的明确赋值状态与位于 expr 之前的 v 的状态相同。 ​ 对于每一个参数 argi,位于 argi 之后的 v 的明确赋值状态由标准表达式规则决定,其中忽略所有的 ref 或 out 修饰符。 ​ 对于每一个 i 大于 1 的参数 argi,位于 argi 之前的 v 的明确赋值状态与位于 argi-1 之后的 v 的状态相同。 ​ 如果变量 v 是被作为 out 参数传送(即,形式为“out v”的参数),则无论将它用作哪一个 argi,在 expr 之后,v 的状态是明确赋值的。否则,位于 expr 之后的 v 的状态与位于 argn 之后的 v 的状态相同。 1.3.3.22简单赋值表达式 对于具有形式 w = expr-rhs 的表达式 expr: ​ 位于 expr-rhs 之前的 v 的明确赋值状态与位于 expr 之前的 v 的明确赋值状态相同。 ​ 如果 w 与 v 是同一变量,则位于 expr 之后的 v 的明确赋值状态是明确赋值的。否则,位于 expr 之后的 v 的明确赋值状态与位于 expr-rhs 之后的 v 的明确赋值状态相同。 1.3.3.23&& 表达式 对于形式为 expr-first && expr-second 的表达式 expr: ​ 位于 expr-first 之前的 v 的明确赋值状态与位于 expr 之前的 v 的明确赋值状态相同。 ​ 如果位于 expr-first 之后的 v 的状态是明确赋值的或为“在 true 表达式后明确赋值”,则位于 expr-second 之前的 v 的明确赋值状态是明确赋值的。否则,它就不是明确赋值的。 ​ 位于 expr 之后的 v 的明确赋值状态取决于: o​ 如果在 expr-first 之后,v 的状态是明确赋值的,则在 expr 之后的 v 的状态也是明确赋值的。 o​ 否则,如果位于 expr-second 之后的 v 的状态是明确赋值的,而且位于 expr-first 之后的 v 的状态为“在 false 表达式后明确赋值”,则位于 expr 之后的 v 的状态是明确赋值的。 o​ 否则,如果位于 expr-second 之后的 v 的状态是明确赋值的或为“在 true 表达式后明确赋值”,则位于 expr 之后的 v 的状态是“在 true 表达式后明确赋值”。 o​ 否则,如果位于 expr-first 之后的 v 的状态是“在 false 表达式后明确赋值”,而且位于 expr-second 之后的 v 的状态是“在 false 表达式后明确赋值”,则位于 expr 之后的 v 的状态是“在 false 表达式后明确赋值”。 o​ 否则,在 expr 之后,v 的状态就不是明确赋值的。 在下面的示例中 class A { static void F(int x, int y) { int i; if (x >= 0 && (i = y) >= 0) { // i definitely assigned } else { // i not definitely assigned } // i not definitely assigned } } 变量 i 被视为在 if 语句的一个嵌入语句中已明确赋值,而在另一个嵌入语句中未明确赋值。在 F 方法中的 if 语句中,由于总是在第一个嵌入语句执行前执行表达式 (i = y),因此变量 i 在第一个嵌入语句中已明确赋值。相反,变量 i 在第二个嵌入语句中没有明确赋值,因为 x >= 0 可能已测试为 false,从而导致变量 i 未赋值。 1.3.3.24|| 表达式 对于形式为 expr-first || expr-second 的表达式 expr: ​ 位于 expr-first 之前的 v 的明确赋值状态与位于 expr 之前的 v 的明确赋值状态相同。 ​ 如果位于 expr-first 之后的 v 的状态是明确赋值的或“在 false 表达式后明确赋值”,则位于 expr-second 之前的 v 的明确赋值状态是明确赋值的。否则,它就不是明确赋值的。 ​ 位于 expr 之后的 v 的明确赋值状态取决于: o​ 如果在 expr-first 之后,v 的状态是明确赋值的,则在 expr 之后的 v 的状态也是明确赋值的。 o​ 否则,如果位于 expr-second 之后的 v 的状态是明确赋值的,而且位于 expr-first 之后的 v 的状态为“在 true 表达式后明确赋值”,则位于 expr 之后的 v 的状态是明确赋值的。 o​ 否则,如果位于 expr-second 之后的 v 的状态是明确赋值的或是“在 false 表达式后明确赋值”,则位于 expr 之后的 v 的状态是“在 false 表达式后明确赋值”。 o​ 否则,如果位于 expr-first 之后的 v 的状态是“在 true 表达式后明确赋值”,而且位于 expr-second 之后的 v 的状态是“在 true 表达式后明确赋值”,则位于 expr 之后的 v 的状态是“在 true 表达式后明确赋值”。 o​ 否则,在 expr 之后,v 的状态就不是明确赋值的。 在下面的示例中 class A { static void G(int x, int y) { int i; if (x >= 0 || (i = y) >= 0) { // i not definitely assigned } else { // i definitely assigned } // i not definitely assigned } } 变量 i 被视为在 if 语句的一个嵌入语句中已明确赋值,而在另一个嵌入语句中未明确赋值。在 G 方法中的 if 语句中,由于总是在第二个嵌入语句执行前执行表达式 (i = y),因此变量 i 在第二个嵌入语句中已明确赋值。相反,在第一个嵌入语句中,变量 i 的状态不是明确赋值的,因为 x >= 0 可能已测试为 true,从而导致变量 i 未赋值。 1.3.3.25! 表达式 对于形式为 ! expr-operand 的表达式 expr: ​ 位于 expr-operand 之前的 v 的明确赋值状态与位于 expr 之前的 v 的明确赋值状态相同。 ​ 位于 expr 之后的 v 的明确赋值状态取决于: o​ 如果在 expr-operand 之后,v 的状态是明确赋值的,则在 expr 之后,v 的状态也是明确赋值的。 o​ 如果在 expr-operand 之后,v 的状态不是明确赋值的,则在 expr 之后,v 的状态也不是明确赋值的。 o​ 如果位于 expr-operand 之后的 v 的状态是“在 false 表达式后明确赋值”,则位于 expr 之后的 v 的状态是“在 true 表达式后明确赋值”。 o​ 如果位于 expr-operand 之后的 v 的状态是“在 true 表达式后明确赋值”,则位于 expr 之后的 v 的状态是“在 false 表达式后明确赋值”。 1.3.3.26?: 表达式 对于形式为 expr-cond ? expr-true : expr-false 的表达式 expr: ​ 位于 expr-cond 之前的 v 的明确赋值状态与位于 expr 之前的 v 的状态相同。 ​ 当且仅当位于 expr-cond 之后的 v 的状态是明确赋值的或“在 true 表达式后明确赋值”时,位于 expr-true 之前的 v 的明确赋值状态才是明确赋值的。 ​ 当且仅当位于 expr-cond 之后的 v 的状态是明确赋值的或“在 false 表达式后明确赋值”时,位于 expr-false 之前的 v 的明确赋值状态才是明确赋值的。 ​ 位于 expr 之后的 v 的明确赋值状态取决于: o​ 如果 expr-cond 是值为 true 的常量表达式(第 7.15 节),则位于 expr 之后的 v 的状态与位于 expr-true 之后的 v 的状态相同。 o​ 否则,如果 expr-cond 是值为 false 的常量表达式(第 7.15 节),则位于 expr 之后的 v 的状态与位于 expr-false 之后的 v 的状态相同。 o​ 否则,如果位于 expr-true 之后的 v 的状态是明确赋值的,而且位于 expr-false 之后的 v 的状态也是明确赋值的,则位于 expr 之后的 v 的状态是明确赋值的。 o​ 否则,在 expr 之后,v 的状态就不是明确赋值的。 1.4变量引用 variable-reference 是一个 expression,它被归类为一个变量。variable-reference 表示一个存储位置,访问它可以获取当前值以及存储新值。 variable-reference: expression 在 C 和 C++ 中,variable-reference 称为 lvalue。 1.5变量引用的原子性 下列数据类型的读写是原子的:bool、char、byte、sbyte、short、ushort、uint、int、float 和引用类型。除此之外,当枚举类型的基础类型的属于上述类型之一时,对它的读写也是原子的。其他类型的读写,包括 long、ulong、double 和 decimal 以及用户定义类型,都不保证是原子的。除专为该目的 设计 领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计 的库函数以外,对于增量或减量这类操作也不能保证进行原子的读、修改和写。
本文档为【C#变量5】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_444161
暂无简介~
格式:doc
大小:166KB
软件:Word
页数:18
分类:互联网
上传时间:2011-10-15
浏览量:28