变量Variables
变量表示存储位置。Variables represent storage locations. 每个变量都有一个类型,用于确定可以在变量中存储的值。Every variable has a type that determines what values can be stored in the variable. C # 是一种类型安全的语言,c # 编译器保证变量中存储的值始终为适当的类型。C# is a type-safe language, and the C# compiler guarantees that values stored in variables are always of the appropriate type. 可以通过赋值或使用和运算符来更改变量的值 ++
--
。The value of a variable can be changed through assignment or through use of the ++
and --
operators.
在获取变量的值之前,必须 明确 地 (明确赋值) 。A variable must be definitely assigned (Definite assignment) before its value can be obtained.
如以下各节中所述,变量为 初始赋值 或 _ 初始未赋值 *。As described in the following sections, variables are either initially assigned _ or _initially unassigned**. 最初分配的变量具有定义完善的初始值,并始终被视为明确赋值。An initially assigned variable has a well-defined initial value and is always considered definitely assigned. 初始未赋值的变量没有初始值。An initially unassigned variable has no initial value. 对于在某个特定位置被视为明确赋值的初始未赋值的变量,对该变量的赋值必须出现在通向该位置的每个可能的执行路径中。For an initially unassigned variable to be considered definitely assigned at a certain location, an assignment to the variable must occur in every possible execution path leading to that location.
变量类别Variable categories
C # 定义了七种类型的变量:静态变量、实例变量、数组元素、值参数、引用参数、输出参数和局部变量。C# defines seven categories of variables: static variables, instance variables, array elements, value parameters, reference parameters, output parameters, and local variables. 以下各节介绍了其中的每个类别。The sections that follow describe each of these categories.
示例中In the example
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
局部变量。x
is a static variable, y
is an instance variable, v[0]
is an array element, a
is a value parameter, b
is a reference parameter, c
is an output parameter, and i
is a local variable.
静态变量Static variables
使用修饰符声明的字段 static
称为 静态变量。A field declared with the static
modifier is called a static variable. 静态变量将在执行静态构造函数 (其包含类型) 静态 构造函数之前存在,并在关联的应用程序域停止存在时停止存在。A static variable comes into existence before execution of the static constructor (Static constructors) for its containing type, and ceases to exist when the associated application domain ceases to exist.
静态变量的初始值是 (默认值) 变量类型的 默认 值。The initial value of a static variable is the default value (Default values) of the variable's type.
出于明确赋值检查的目的,静态变量被视为初始赋值。For purposes of definite assignment checking, a static variable is considered initially assigned.
实例变量Instance variables
不使用修饰符声明的字段 static
称为 实例变量。A field declared without the static
modifier is called an instance variable.
类中的实例变量Instance variables in classes
当创建该类的新实例时,该类的实例变量就会成为存在,当不存在对该实例和实例的析构函数(如果已执行任何) ()时,该类的实例将停止存在。An instance variable of a class comes into existence when a new instance of that class is created, and ceases to exist when there are no references to that instance and the instance's destructor (if any) has executed.
类的实例变量的初始值是 (默认值) 变量类型的 默认 值。The initial value of an instance variable of a class is the default value (Default values) of the variable's type.
出于明确赋值检查的目的,类的实例变量被视为初始赋值。For the purpose of definite assignment checking, an instance variable of a class is considered initially assigned.
结构中的实例变量Instance variables in structs
结构的实例变量与它所属的结构变量的生存期完全相同。An instance variable of a struct has exactly the same lifetime as the struct variable to which it belongs. 换而言之,当结构类型的变量变为存在或不再存在时,该结构的实例变量也是如此。In other words, when a variable of a struct type comes into existence or ceases to exist, so too do the instance variables of the struct.
结构的实例变量的初始赋值状态与包含结构变量的初始赋值状态相同。The initial assignment state of an instance variable of a struct is the same as that of the containing struct variable. 换言之,当结构变量被视为初始已赋值,因此它的实例变量也被视为未赋值时,它的实例变量会同样取消分配。In other words, when a struct variable is considered initially assigned, so too are its instance variables, and when a struct variable is considered initially unassigned, its instance variables are likewise unassigned.
数组元素Array elements
当创建数组实例时,数组的元素便会存在,并且在没有对该数组实例的引用时停止存在。The elements of an array come into existence when an array instance is created, and cease to exist when there are no references to that array instance.
数组中每个元素的初始值都是默认值 (数组元素类型) 默认值 。The initial value of each of the elements of an array is the default value (Default values) of the type of the array elements.
出于明确赋值检查的目的,数组元素被视为初始已赋值。For the purpose of definite assignment checking, an array element is considered initially assigned.
值参数Value parameters
不带或修饰符声明的参数 ref
out
是一个 值参数。A parameter declared without a ref
or out
modifier is a value parameter.
值参数可在调用函数成员 (方法、实例构造函数、访问器或运算符) 或参数所属的匿名函数时存在,并使用调用中给定的参数的值进行初始化。A value parameter comes into existence upon invocation of the function member (method, instance constructor, accessor, or operator) or anonymous function to which the parameter belongs, and is initialized with the value of the argument given in the invocation. 当函数成员或匿名函数返回时,值参数通常不存在。A value parameter normally ceases to exist upon return of the function member or anonymous function. 但是,如果通过匿名函数捕获 value 参数 (匿名函数表达式) ,则它的生存期将至少延长到从该匿名函数创建的委托或表达式树符合垃圾回收的条件。However, if the value parameter is captured by an anonymous function (Anonymous function expressions), its life time extends at least until the delegate or expression tree created from that anonymous function is eligible for garbage collection.
出于明确赋值检查的目的,值参数被视为初始已赋值。For the purpose of definite assignment checking, a value parameter is considered initially assigned.
引用参数Reference parameters
使用修饰符声明的参数 ref
是一个 引用参数。A parameter declared with a ref
modifier is a reference parameter.
引用参数不会创建新的存储位置。A reference parameter does not create a new storage location. 相反,引用参数与给定作为函数成员或匿名函数调用中的参数的变量表示相同的存储位置。Instead, a reference parameter represents the same storage location as the variable given as the argument in the function member or anonymous function invocation. 因此,引用参数的值始终与基础变量相同。Thus, the value of a reference parameter is always the same as the underlying variable.
以下明确赋值规则适用于引用参数。The following definite assignment rules apply to reference parameters. 请注意 输出参数中所述的输出参数的不同规则。Note the different rules for output parameters described in Output parameters.
- 在函数成员或委托调用中将变量作为引用参数传递时,必须明确地 (明确赋值) 赋值。A variable must be definitely assigned (Definite assignment) before it can be passed as a reference parameter in a function member or delegate invocation.
- 在函数成员或匿名函数中,引用参数被视为初始赋值。Within a function member or anonymous function, a reference parameter is considered initially assigned.
在结构类型的实例方法或实例访问器中, this
关键字的行为与 此访问) (结构类型的引用参数完全相同。Within an instance method or instance accessor of a struct type, the this
keyword behaves exactly as a reference parameter of the struct type (This access).
输出参数Output parameters
使用修饰符声明的参数 out
是一个 输出参数。A parameter declared with an out
modifier is an output parameter.
Output 参数不会创建新的存储位置。An output parameter does not create a new storage location. 相反,output 参数表示作为函数成员或委托调用中的参数提供的相同存储位置。Instead, an output parameter represents the same storage location as the variable given as the argument in the function member or delegate invocation. 因此,output 参数的值始终与基础变量相同。Thus, the value of an output parameter is always the same as the underlying variable.
以下明确的赋值规则适用于 output 参数。The following definite assignment rules apply to output parameters. 请注意 引用参数中所述的引用参数的不同规则。Note the different rules for reference parameters described in Reference parameters.
- 在函数成员或委托调用中将变量作为 output 参数传递之前,不需要明确赋值。A variable need not be definitely assigned before it can be passed as an output parameter in a function member or delegate invocation.
- 完成函数成员或委托调用的正常完成后,作为输出参数传递的每个变量都被视为在该执行路径中分配。Following the normal completion of a function member or delegate invocation, each variable that was passed as an output parameter is considered assigned in that execution path.
- 在函数成员或匿名函数中,output 参数被视为初始未赋值。Within a function member or anonymous function, an output parameter is considered initially unassigned.
- 函数成员或匿名函数的每个输出参数都必须在函数成员或匿名函数正常返回之前 (明确赋值) 。Every output parameter of a function member or anonymous function must be definitely assigned (Definite assignment) before the function member or anonymous function returns normally.
在结构类型的实例构造函数中, this
关键字的行为与 此访问) (结构类型的输出参数完全相同。Within an instance constructor of a struct type, the this
keyword behaves exactly as an output parameter of the struct type (This access).
局部变量Local variables
*本地变量 _ 由 _local_variable_declaration * 声明,后者可能出现在 块、 for_statement、 switch_statement 或 using_statement 中;或由 try_statement foreach_statement 或 specific_catch_clause 。A local variable _ is declared by a _local_variable_declaration, which may occur in a block, a for_statement, a switch_statement or a using_statement; or by a foreach_statement or a specific_catch_clause for a try_statement.
局部变量的生存期是程序执行的一部分,在该过程中,将保证存储的存储空间。The lifetime of a local variable is the portion of program execution during which storage is guaranteed to be reserved for it. 此生存期至少会将输入中的内容扩展到 块、 for_statement、 switch_statement、 using_statement、 foreach_statement 或与之关联的 specific_catch_clause ,直到该 块 的执行、 for_statement、 switch_statement、 using_statement、 foreach_statement 或 specific_catch_clause 以任何方式结束。This lifetime extends at least from entry into the block, for_statement, switch_statement, using_statement, foreach_statement, or specific_catch_clause with which it is associated, until execution of that block, for_statement, switch_statement, using_statement, foreach_statement, or specific_catch_clause ends in any way. (进入封闭的 块 或调用方法挂起,但不是结束、执行当前 块、 for_statement、 switch_statement、 using_statement、 foreach_statement 或 specific_catch_clause。如果本地变量是由匿名函数捕获 ) 捕获的外部变量 (,则它的生存期至少会持续到从匿名函数创建的委托或表达式树以及引用捕获的变量的任何其他对象,可用于垃圾回收。(Entering an enclosed block or calling a method suspends, but does not end, execution of the current block, for_statement, switch_statement, using_statement, foreach_statement, or specific_catch_clause.) If the local variable is captured by an anonymous function (Captured outer variables), its lifetime extends at least until the delegate or expression tree created from the anonymous function, along with any other objects that come to reference the captured variable, are eligible for garbage collection.
如果以递归方式进入父 块、 for_statement、 switch_statement、 using_statement、 foreach_statement 或 specific_catch_clause ,则每次都会创建一个新的局部变量,并且每次都会计算其 local_variable_initializer(如果有)。If the parent block, for_statement, switch_statement, using_statement, foreach_statement, or specific_catch_clause is entered recursively, a new instance of the local variable is created each time, and its local_variable_initializer, if any, is evaluated each time.
Local_variable_declaration 引入的本地变量不会自动初始化,因此没有默认值。A local variable introduced by a local_variable_declaration is not automatically initialized and thus has no default value. 出于明确赋值检查的目的,由 local_variable_declaration 引入的局部变量被视为初始未赋值。For the purpose of definite assignment checking, a local variable introduced by a local_variable_declaration is considered initially unassigned. Local_variable_declaration 可能包括 local_variable_initializer,在这种情况下,仅在初始化表达式 (声明语句) 后,才将变量视为明确赋值。A local_variable_declaration may include a local_variable_initializer, in which case the variable is considered definitely assigned only after the initializing expression (Declaration statements).
在 local_variable_declaration 引入的本地变量的作用域内,在其 local_variable_declarator 之前的文本位置引用该局部变量是编译时错误。Within the scope of a local variable introduced by a local_variable_declaration, it is a compile-time error to refer to that local variable in a textual position that precedes its local_variable_declarator. 如果局部变量声明为隐式 (局部变量声明) ,则在其 local_variable_declarator 内引用该变量也是错误的。If the local variable declaration is implicit (Local variable declarations), it is also an error to refer to the variable within its local_variable_declarator.
Foreach_statement 或 specific_catch_clause 所引入的局部变量在整个范围内被视为已明确赋值。A local variable introduced by a foreach_statement or a specific_catch_clause is considered definitely assigned in its entire scope.
局部变量的实际生存期取决于实现。The actual lifetime of a local variable is implementation-dependent. 例如,编译器可能会以静态方式确定块中的某个局部变量仅用于该块的一小部分。For example, a compiler might statically determine that a local variable in a block is only used for a small portion of that block. 使用此分析,编译器可以生成代码,使变量的存储具有比包含块更短的生存期。Using this analysis, the compiler could generate code that results in the variable's storage having a shorter lifetime than its containing block.
局部引用变量所引用的存储将在本地引用变量的生存期内被回收,这 (自动内存管理) 。The storage referred to by a local reference variable is reclaimed independently of the lifetime of that local reference variable (Automatic memory management).
默认值Default values
以下类别的变量会自动初始化为其默认值:The following categories of variables are automatically initialized to their default values:
- 静态变量。Static variables.
- 类实例的实例变量。Instance variables of class instances.
- 数组元素。Array elements.
变量的默认值取决于变量的类型,并按如下所示确定:The default value of a variable depends on the type of the variable and is determined as follows:
- 对于 value_type 的变量,默认值与 value_type 的默认构造函数 (默认 构造函数) 计算的值相同。For a variable of a value_type, the default value is the same as the value computed by the value_type's default constructor (Default constructors).
- 对于 reference_type 的变量,默认值为
null
。For a variable of a reference_type, the default value isnull
.
默认值的初始化通常是通过使内存管理器或垃圾回收器将内存初始化为全部位零来完成的,然后再将其分配给使用。Initialization to default values is typically done by having the memory manager or garbage collector initialize memory to all-bits-zero before it is allocated for use. 出于此原因,可以方便地使用所有位数表示空引用。For this reason, it is convenient to use all-bits-zero to represent the null reference.
明确赋值Definite assignment
在函数成员的可执行代码中的给定位置,如果编译器可以通过特定的静态流分析 (确定明确赋值) 的精确规则,则将变量称为 明确 赋值,该变量已自动初始化或已成为至少一个赋值的目标。At a given location in the executable code of a function member, a variable is said to be definitely assigned if the compiler can prove, by a particular static flow analysis (Precise rules for determining definite assignment), that the variable has been automatically initialized or has been the target of at least one assignment. 非正式地说,明确赋值的规则如下:Informally stated, the rules of definite assignment are:
- 最初分配的变量 (初始分配 的变量,) 始终被视为明确赋值。An initially assigned variable (Initially assigned variables) is always considered definitely assigned.
- 初始未赋值的变量 (初始未分配的变量 ,如果在指定位置有所有可能的执行路径至少包含以下内容之一,则会将其视为在给定位置明确赋值) :An initially unassigned variable (Initially unassigned variables) is considered definitely assigned at a given location if all possible execution paths leading to that location contain at least one of the following:
- 简单的赋值 (简单的赋值) ,其中变量是左操作数。A simple assignment (Simple assignment) in which the variable is the left operand.
- 调用表达式 (调用 表达式) 或对象创建表达式 (对象创建 表达式) ,后者将变量作为输出参数进行传递。An invocation expression (Invocation expressions) or object creation expression (Object creation expressions) that passes the variable as an output parameter.
- 对于局部变量,本地变量声明 (包含变量初始值设定项) 局部变量声明 。For a local variable, a local variable declaration (Local variable declarations) that includes a variable initializer.
最初分配的变量、最初未分配的变量和用于确定明确赋值的精确规则中介绍了上述非正式规则基础的正式规范。The formal specification underlying the above informal rules is described in Initially assigned variables, Initially unassigned variables, and Precise rules for determining definite assignment.
单独跟踪 struct_type 变量的实例变量的明确赋值状态。The definite assignment states of instance variables of a struct_type variable are tracked individually as well as collectively. 除了以上规则,以下规则适用于 struct_type 变量及其实例变量:In addition to the rules above, the following rules apply to struct_type variables and their instance variables:
- 如果实例变量的包含 struct_type 变量被视为已明确赋值,则将其视为明确赋值。An instance variable is considered definitely assigned if its containing struct_type variable is considered definitely assigned.
- 如果将 struct_type 变量视为已明确赋值,则将其视为明确赋值。A struct_type variable is considered definitely assigned if each of its instance variables is considered definitely assigned.
在以下上下文中,明确赋值是必需的:Definite assignment is a requirement in the following contexts:
- 变量必须在获取其值的每个位置明确赋值。A variable must be definitely assigned at each location where its value is obtained. 这可确保永远不会出现未定义的值。This ensures that undefined values never occur. 表达式中的变量的出现位置被视为获取该变量的值,但在The occurrence of a variable in an expression is considered to obtain the value of the variable, except when
- 变量是简单赋值的左操作数,the variable is the left operand of a simple assignment,
- 变量作为 output 参数传递,或the variable is passed as an output parameter, or
- 变量是 struct_type 变量,作为成员访问的左操作数出现。the variable is a struct_type variable and occurs as the left operand of a member access.
- 变量必须在作为引用参数传递的每个位置上进行明确赋值。A variable must be definitely assigned at each location where it is passed as a reference parameter. 这可确保被调用的函数成员可以考虑最初分配的引用参数。This ensures that the function member being invoked can consider the reference parameter initially assigned.
- 函数成员的所有输出参数都必须在函数成员通过语句返回 (的每个位置上进行明确赋值,
return
或通过执行到达函数成员主体的末尾) 。All output parameters of a function member must be definitely assigned at each location where the function member returns (through areturn
statement or through execution reaching the end of the function member body). 这可确保函数成员不在输出参数中返回未定义的值,从而使编译器可以考虑使用变量作为输出参数的函数成员调用,该参数等效于对变量赋值的输出参数。This ensures that function members do not return undefined values in output parameters, thus enabling the compiler to consider a function member invocation that takes a variable as an output parameter equivalent to an assignment to the variable. this
Struct_type 实例构造函数的变量在该实例构造函数返回的每个位置都必须明确赋值。Thethis
variable of a struct_type instance constructor must be definitely assigned at each location where that instance constructor returns.
最初分配的变量Initially assigned variables
以下类别的变量被分类为初始分配:The following categories of variables are classified as initially assigned:
- 静态变量。Static variables.
- 类实例的实例变量。Instance variables of class instances.
- 最初分配的结构变量的实例变量。Instance variables of initially assigned struct variables.
- 数组元素。Array elements.
- 值参数。Value parameters.
- 引用参数。Reference parameters.
catch
子句或语句中声明的变量foreach
。Variables declared in acatch
clause or aforeach
statement.
初始未赋值变量Initially unassigned variables
以下类别的变量被分类为初始未赋值:The following categories of variables are classified as initially unassigned:
- 初始未分配的结构变量的实例变量。Instance variables of initially unassigned struct variables.
- 输出参数,包括
this
结构实例构造函数的变量。Output parameters, including thethis
variable of struct instance constructors. - 局部变量(子句或语句中声明的变量除外)
catch
foreach
。Local variables, except those declared in acatch
clause or aforeach
statement.
确定明确赋值的精确规则Precise rules for determining definite assignment
为了确定每个已使用的变量是否已明确赋值,编译器必须使用与本部分中所述等效的进程。In order to determine that each used variable is definitely assigned, the compiler must use a process that is equivalent to the one described in this section.
编译器处理每个具有一个或多个初始未赋值变量的函数成员的正文。The compiler processes the body of each function member that has one or more initially unassigned variables. 对于每个初始未赋值的变量 v,编译器会在函数成员的以下各点确定 _v * 的 *明确赋值状态 _:For each initially unassigned variable v, the compiler determines a definite assignment state _ for _v at each of the following points in the function member:
- 在每个语句的开头At the beginning of each statement
- 在终结点 (每个语句的 终结点和可访问 性) At the end point (End points and reachability) of each statement
- 在将控制转移到另一条语句或语句结束点的每个弧线上On each arc which transfers control to another statement or to the end point of a statement
- 在每个表达式的开头At the beginning of each expression
- 在每个表达式的末尾At the end of each expression
V 的明确赋值状态可以是:The definite assignment state of v can be either:
- 明确赋值。Definitely assigned. 这表明,在所有可能的控制流到目前为止, v 已分配有一个值。This indicates that on all possible control flows to this point, v has been assigned a value.
- 未明确赋值。Not definitely assigned. 对于类型为的表达式末尾的变量状态
bool
,未明确赋值的变量的状态可能 (但不一定) 属于以下子状态之一:For the state of a variable at the end of an expression of typebool
, the state of a variable that isn't definitely assigned may (but doesn't necessarily) fall into one of the following sub-states:- 在 true 表达式后明确赋值。Definitely assigned after true expression. 此状态表明,如果布尔表达式的计算结果为 true,则会明确赋值 v ; 如果布尔表达式的计算结果为 false,则不一定赋值。This state indicates that v is definitely assigned if the boolean expression evaluated as true, but is not necessarily assigned if the boolean expression evaluated as false.
- 在 false 表达式后明确赋值。Definitely assigned after false expression. 此状态表明,如果布尔表达式的计算结果为 false,则会明确赋值 v ; 如果布尔表达式的计算结果为 true,则不一定赋值。This state indicates that v is definitely assigned if the boolean expression evaluated as false, but is not necessarily assigned if the boolean expression evaluated as true.
以下规则控制如何在每个位置确定变量 v 的状态。The following rules govern how the state of a variable v is determined at each location.
语句的一般规则General rules for statements
- 在函数成员主体的开头, v 未明确赋值。v is not definitely assigned at the beginning of a function member body.
- 在任何无法访问的语句开始时,均明确赋值 v 。v is definitely assigned at the beginning of any unreachable statement.
- V 在任何其他语句开始时的明确赋值状态是通过检查 v 在该语句开头的所有控制流传输上的明确赋值状态。The definite assignment state of v at the beginning of any other statement is determined by checking the definite assignment state of v on all control flow transfers that target the beginning of that statement. 如果 (并且仅当在所有此类控制流传输上都明确分配) v 时,则在语句开头明确赋值 v 。If (and only if) v is definitely assigned on all such control flow transfers, then v is definitely assigned at the beginning of the statement. 可以按照与检查语句可访问性相同的方式确定一组可能的控制流传输 (终结点和可访问 性) 。The set of possible control flow transfers is determined in the same way as for checking statement reachability (End points and reachability).
- 在块、、、、、、、、或语句的终结点上, v 的明确赋值状态
checked
unchecked
if
while
do
for
foreach
lock
using
switch
是通过在所有控制流传输上检查 v 的明确赋值状态,该状态针对该语句的终结点。The definite assignment state of v at the end point of a block,checked
,unchecked
,if
,while
,do
,for
,foreach
,lock
,using
, orswitch
statement is determined by checking the definite assignment state of v on all control flow transfers that target the end point of that statement. 如果对所有此类控制流传输明确赋值 v ,则 v 在语句的终结点上是明确赋值的。If v is definitely assigned on all such control flow transfers, then v is definitely assigned at the end point of the statement. 本来在语句的结束点上不明确赋值 v 。Otherwise; v is not definitely assigned at the end point of the statement. 可以按照与检查语句可访问性相同的方式确定一组可能的控制流传输 (终结点和可访问 性) 。The set of possible control flow transfers is determined in the same way as for checking statement reachability (End points and reachability).
Block 语句、checked 和 unchecked 语句Block statements, checked, and unchecked statements
如果语句列表为空,则在将控件传输到块中语句列表的第一条语句时,将控件上的 v 的明确赋值状态传输到块的第一条语句,如果语句列表为空) ,则为与块、或语句前面的 v 的明确赋值语句 (checked
unchecked
。The definite assignment state of v on the control transfer to the first statement of the statement list in the block (or to the end point of the block, if the statement list is empty) is the same as the definite assignment statement of v before the block, checked
, or unchecked
statement.
表达式语句Expression statements
对于包含表达式 expr 的表达式语句 stmt :For an expression statement stmt that consists of the expression expr:
- 在 stmt 开始时, v 在 expr 开头具有相同的明确赋值状态。v has the same definite assignment state at the beginning of expr as at the beginning of stmt.
- 如果在 expr 的末尾指定了 " v ",则它在 stmt 的终结点上进行明确赋值;本来它不是在 stmt 终结点明确赋值的。If v if definitely assigned at the end of expr, it is definitely assigned at the end point of stmt; otherwise; it is not definitely assigned at the end point of stmt.
声明语句Declaration statements
- 如果 stmt 是没有初始值设定项的声明语句,则 v 在 stmt 的终结点上的明确赋值状态与 stmt 的开头相同。If stmt is a declaration statement without initializers, then v has the same definite assignment state at the end point of stmt as at the beginning of stmt.
- 如果 stmt 是带有初始值设定项的声明语句,则 v 的明确赋值状态被确定为: stmt 是语句列表,每个具有初始值设定项的声明的赋值语句) (。If stmt is a declaration statement with initializers, then the definite assignment state for v is determined as if stmt were a statement list, with one assignment statement for each declaration with an initializer (in the order of declaration).
If 语句If statements
对于 if
窗体的语句 stmt :For an if
statement stmt of the form:
if ( expr ) then_stmt else else_stmt
- 在 stmt 开始时, v 在 expr 开头具有相同的明确赋值状态。v has the same definite assignment state at the beginning of expr as at the beginning of stmt.
- 如果在 expr 结束时, v 是明确赋值的,则在控制流传输到 then_stmt ,并将其分配到 else_stmt ,或者在没有 else 子句的情况下将其分配给 stmt 的终结点。If v is definitely assigned at the end of expr, then it is definitely assigned on the control flow transfer to then_stmt and to either else_stmt or to the end-point of stmt if there is no else clause.
- 如果在 expr 的末尾, v 的状态为 "明确分配给 true 表达式",则它在控制流到 then_stmt 的传输中是明确赋值的,如果不存在 else 子句,则不会在控制流传输上明确分配到 else_stmt 或到 stmt 的终结点。If v has the state "definitely assigned after true expression" at the end of expr, then it is definitely assigned on the control flow transfer to then_stmt, and not definitely assigned on the control flow transfer to either else_stmt or to the end-point of stmt if there is no else clause.
- 如果 v 在 expr 的末尾具有状态 "在假表达式后明确赋值",则它将在控制流传输上明确分配到 else_stmt,而不是明确分配给 then_stmt 的控制流传输。If v has the state "definitely assigned after false expression" at the end of expr, then it is definitely assigned on the control flow transfer to else_stmt, and not definitely assigned on the control flow transfer to then_stmt. 当且仅当在 then_stmt 的终结点明确赋值时,它才会在 stmt 的终结点上进行明确赋值。It is definitely assigned at the end-point of stmt if and only if it is definitely assigned at the end-point of then_stmt.
- 否则,在控制流到 then_stmt 或 else_stmt 的控制流传输上, v 被视为未明确分配,如果不存在 else 子句,则被视为 stmt 的终结点。Otherwise, v is considered not definitely assigned on the control flow transfer to either the then_stmt or else_stmt, or to the end-point of stmt if there is no else clause.
Switch 语句Switch statements
switch
使用控制表达式 expr 的语句 stmt :In a switch
statement stmt with a controlling expression expr:
- Expr 开头的 v 的明确赋值状态与 stmt 开头的 v 的状态相同。The definite assignment state of v at the beginning of expr is the same as the state of v at the beginning of stmt.
- 到可访问的 switch 块语句列表的控制流传输上, v 的明确分配状态与 expr 末尾的 v 的明确赋值状态相同。The definite assignment state of v on the control flow transfer to a reachable switch block statement list is the same as the definite assignment state of v at the end of expr.
While 语句While statements
对于 while
窗体的语句 stmt :For a while
statement stmt of the form:
while ( expr ) while_body
- 在 stmt 开始时, v 在 expr 开头具有相同的明确赋值状态。v has the same definite assignment state at the beginning of expr as at the beginning of stmt.
- 如果在 expr 结束时, v 是明确赋值的,则它在控制流传输上明确分配到 while_body 和 stmt 的终结点。If v is definitely assigned at the end of expr, then it is definitely assigned on the control flow transfer to while_body and to the end point of stmt.
- 如果在 expr 的末尾, v 的状态为 "明确分配给 true 表达式",则它在控制流传输上明确分配到 while_body,而不是在 stmt 的终结点明确赋值。If v has the state "definitely assigned after true expression" at the end of expr, then it is definitely assigned on the control flow transfer to while_body, but not definitely assigned at the end-point of stmt.
- 如果 v 在 expr 的末尾具有状态 "在假表达式后明确赋值",则它在控制流到 stmt 的终点的控制流传输上明确赋值,但并没有明确地分配给 while_body 的控制流传输。If v has the state "definitely assigned after false expression" at the end of expr, then it is definitely assigned on the control flow transfer to the end point of stmt, but not definitely assigned on the control flow transfer to while_body.
Do 语句Do statements
对于 do
窗体的语句 stmt :For a do
statement stmt of the form:
do do_body while ( expr ) ;
- 在从 stmt 开始到 do_body 时, v 在控制流传输上具有相同的明确赋值状态,如 stmt 的开头。v has the same definite assignment state on the control flow transfer from the beginning of stmt to do_body as at the beginning of stmt.
- 在 expr 的开头, v 与 do_body 的终结点具有相同的明确赋值状态。v has the same definite assignment state at the beginning of expr as at the end point of do_body.
- 如果在 expr 结束时, v 是明确赋值的,则它在控制流到 stmt 终点的传输上明确赋值。If v is definitely assigned at the end of expr, then it is definitely assigned on the control flow transfer to the end point of stmt.
- 如果在 expr 的末尾, v 的状态为 "在假表达式后明确赋值",则它在控制流到 stmt 终点的传输上明确赋值。If v has the state "definitely assigned after false expression" at the end of expr, then it is definitely assigned on the control flow transfer to the end point of stmt.
For 语句For statements
对以下形式的语句的明确赋值检查 for
:Definite assignment checking for a for
statement of the form:
for ( for_initializer ; for_condition ; for_iterator ) embedded_statement
像编写语句一样完成:is done as if the statement were written:
{
for_initializer ;
while ( for_condition ) {
embedded_statement ;
for_iterator ;
}
}
如果语句中省略了 for_condition for
,则计算明确赋值将继续,就像上述扩展中的 for_condition 已替换为 true
。If the for_condition is omitted from the for
statement, then evaluation of definite assignment proceeds as if for_condition were replaced with true
in the above expansion.
Break、continue 和 goto 语句Break, continue, and goto statements
由、或语句导致的控制流传输上的 v 的明确赋值状态与 break
continue
goto
语句开头的 v 的明确赋值状态相同。The definite assignment state of v on the control flow transfer caused by a break
, continue
, or goto
statement is the same as the definite assignment state of v at the beginning of the statement.
Throw 语句Throw statements
对于窗体的语句 stmtFor a statement stmt of the form
throw expr ;
Expr 开头的 v 的明确赋值状态与 stmt 开头的 v 的明确赋值状态相同。The definite assignment state of v at the beginning of expr is the same as the definite assignment state of v at the beginning of stmt.
Return 语句Return statements
对于窗体的语句 stmtFor a statement stmt of the form
return expr ;
- Expr 开头的 v 的明确赋值状态与 stmt 开头的 v 的明确赋值状态相同。The definite assignment state of v at the beginning of expr is the same as the definite assignment state of v at the beginning of stmt.
- 如果 v 是 output 参数,则必须为其赋值:If v is an output parameter, then it must be definitely assigned either:
- expr 之后after expr
- 或包含语句的块的结尾
finally
try
-finally
try
-catch
-finally
return
。or at the end of thefinally
block of atry
-finally
ortry
-catch
-finally
that encloses thereturn
statement.
对于窗体的语句 stmt:For a statement stmt of the form:
return ;
- 如果 v 是 output 参数,则必须为其赋值:If v is an output parameter, then it must be definitely assigned either:
- stmt 之前before stmt
- 或包含语句的块的结尾
finally
try
-finally
try
-catch
-finally
return
。or at the end of thefinally
block of atry
-finally
ortry
-catch
-finally
that encloses thereturn
statement.
Try-catch 语句Try-catch statements
对于窗体的语句 stmt :For a statement stmt of the form:
try try_block
catch(...) catch_block_1
...
catch(...) catch_block_n
- 在 try_block 开始时, v 的明确赋值状态与 stmt 开头的 v 的明确赋值状态相同。The definite assignment state of v at the beginning of try_block is the same as the definite assignment state of v at the beginning of stmt.
- 任何 i) catch_block_i (的开头的 v 的明确分配状态与 stmt 开头的 v 的明确赋值状态相同。The definite assignment state of v at the beginning of catch_block_i (for any i) is the same as the definite assignment state of v at the beginning of stmt.
- 如果 (并且仅当) v 在 try_block 的终结点上明确分配,并且每个 catch_block_i (每个 ) 的 每个 ,则该终结点的终结点的明确赋值 状态将明确 赋值。The definite assignment state of v at the end-point of stmt is definitely assigned if (and only if) v is definitely assigned at the end-point of try_block and every catch_block_i (for every i from 1 to n).
Try-catch 语句Try-finally statements
对于 try
窗体的语句 stmt :For a try
statement stmt of the form:
try try_block finally finally_block
- 在 try_block 开始时, v 的明确赋值状态与 stmt 开头的 v 的明确赋值状态相同。The definite assignment state of v at the beginning of try_block is the same as the definite assignment state of v at the beginning of stmt.
- 在 finally_block 开始时, v 的明确赋值状态与 stmt 开头的 v 的明确赋值状态相同。The definite assignment state of v at the beginning of finally_block is the same as the definite assignment state of v at the beginning of stmt.
- 如果 (并且仅当) 至少满足以下条件之一时,就会明确分配 v 在 stmt 终结点上的明确分配状态:The definite assignment state of v at the end-point of stmt is definitely assigned if (and only if) at least one of the following is true:
- v 在 try_block 的终结点明确赋值v is definitely assigned at the end-point of try_block
- v 在 finally_block 的终结点明确赋值v is definitely assigned at the end-point of finally_block
例如,如果控制流传输 (例如, goto
语句) 在 try_block 内开始,并在 try_block 外结束,则在该控制流传输上, v 也被视为明确分配,前提是在 finally_block 的终结点明确赋值 v 。If a control flow transfer (for example, a goto
statement) is made that begins within try_block, and ends outside of try_block, then v is also considered definitely assigned on that control flow transfer if v is definitely assigned at the end-point of finally_block. (这种情况并不是唯一的情况,如果对此控制流传输的另一个原因明确指定 v ,则仍将其视为明确赋值。 ) (This is not an only if—if v is definitely assigned for another reason on this control flow transfer, then it is still considered definitely assigned.)
Try-catch-finally 语句Try-catch-finally statements
对 try
- catch
- finally
以下形式的语句的明确赋值分析:Definite assignment analysis for a try
-catch
-finally
statement of the form:
try try_block
catch(...) catch_block_1
...
catch(...) catch_block_n
finally *finally_block*
如语句是 try
- finally
包含语句的语句一样完成 try
- catch
:is done as if the statement were a try
-finally
statement enclosing a try
-catch
statement:
try {
try try_block
catch(...) catch_block_1
...
catch(...) catch_block_n
}
finally finally_block
下面的示例演示了 try
try 语句 (的 语句的不同块如何) 影响明确赋值。The following example demonstrates how the different blocks of a try
statement (The try statement) affect definite assignment.
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
}
}
Foreach 语句Foreach statements
对于 foreach
窗体的语句 stmt :For a foreach
statement stmt of the form:
foreach ( type identifier in expr ) embedded_statement
- Expr 开头的 v 的明确赋值状态与 stmt 开头的 v 的状态相同。The definite assignment state of v at the beginning of expr is the same as the state of v at the beginning of stmt.
- 控制流传输到 embedded_statement 或 stmt 终结点上的 v 的明确分配状态与 expr 末尾处的 v 状态相同。The definite assignment state of v on the control flow transfer to embedded_statement or to the end point of stmt is the same as the state of v at the end of expr.
使用语句Using statements
对于 using
窗体的语句 stmt :For a using
statement stmt of the form:
using ( resource_acquisition ) embedded_statement
- 在 resource_acquisition 开始时, v 的明确赋值状态与 stmt 开头的 v 状态相同。The definite assignment state of v at the beginning of resource_acquisition is the same as the state of v at the beginning of stmt.
- 控制流传输到 embedded_statement 的 v 的明确分配状态与 resource_acquisition 末尾处的 v 状态相同。The definite assignment state of v on the control flow transfer to embedded_statement is the same as the state of v at the end of resource_acquisition.
Lock 语句Lock statements
对于 lock
窗体的语句 stmt :For a lock
statement stmt of the form:
lock ( expr ) embedded_statement
- Expr 开头的 v 的明确赋值状态与 stmt 开头的 v 的状态相同。The definite assignment state of v at the beginning of expr is the same as the state of v at the beginning of stmt.
- 控制流传输到 embedded_statement 的 v 的明确分配状态与 expr 末尾处的 v 状态相同。The definite assignment state of v on the control flow transfer to embedded_statement is the same as the state of v at the end of expr.
Yield 语句Yield statements
对于 yield return
窗体的语句 stmt :For a yield return
statement stmt of the form:
yield return expr ;
- Expr 开头的 v 的明确赋值状态与 stmt 开头的 v 的状态相同。The definite assignment state of v at the beginning of expr is the same as the state of v at the beginning of stmt.
- 在 stmt 结束时, v 的明确赋值状态与 expr 末尾的 v 状态相同。The definite assignment state of v at the end of stmt is the same as the state of v at the end of expr.
yield break
语句对明确赋值状态没有影响。Ayield break
statement has no effect on the definite assignment state.
简单表达式的一般规则General rules for simple expressions
以下规则适用于这些类型的表达式:文本 (文本) ,简单名称 (简单名称) ,成员访问表达式 (成员访问) ,非索引的基本访问表达式 (基本访问) , typeof
表达式 (typeof 运算符) ,默认值表达式 (默认值 表达式) 和 (nameof
Nameof 表达式) 默认值表达式。The following rule applies to these kinds of expressions: literals (Literals), simple names (Simple names), member access expressions (Member access), non-indexed base access expressions (Base access), typeof
expressions (The typeof operator), default value expressions (Default value expressions) and nameof
expressions (Nameof expressions).
- 此类表达式结束时, v 的明确赋值状态与表达式开头 v 的明确赋值状态相同。The definite assignment state of v at the end of such an expression is the same as the definite assignment state of v at the beginning of the expression.
带有嵌入式表达式的表达式的一般规则General rules for expressions with embedded expressions
以下规则适用于这些类型的表达式:带圆括号的表达式 (带圆括号的表达式) ,元素访问表达式 (元素访问) ,使用索引编制索引的基本访问表达式 (基本访问) 、递增和递减表达式 (后缀增量和减量运算符、前缀增量和减量运算符) 、转换表达式 (强制转换表达式) 一元、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、) +
-
~
*
+
-
*
/
%
<<
>>
<
<=
>
>=
==
!=
is
as
&
|
^
、复合赋值表达式 (复合赋值) 和 checked
表达式 (new unchecked
运算符) (、数组和委托创建表达式) 。 (The following rules apply to these kinds of expressions: parenthesized expressions (Parenthesized expressions), element access expressions (Element access), base access expressions with indexing (Base access), increment and decrement expressions (Postfix increment and decrement operators, Prefix increment and decrement operators), cast expressions (Cast expressions), unary +
, -
, ~
, *
expressions, binary +
, -
, *
, /
, %
, <<
, >>
, <
, <=
, >
, >=
, ==
, !=
, is
, as
, &
, |
, ^
expressions (Arithmetic operators, Shift operators, Relational and type-testing operators, Logical operators), compound assignment expressions (Compound assignment), checked
and unchecked
expressions (The checked and unchecked operators), plus array and delegate creation expressions (The new operator).
其中每个表达式都具有一个或多个按固定顺序无条件计算的子表达式。Each of these expressions has one or more sub-expressions that are unconditionally evaluated in a fixed order. 例如,二元 %
运算符计算运算符的左侧,然后计算右侧。For example, the binary %
operator evaluates the left hand side of the operator, then the right hand side. 索引操作将计算索引表达式的值,然后按从左至右的顺序计算每个索引表达式。An indexing operation evaluates the indexed expression, and then evaluates each of the index expressions, in order from left to right. 对于具有子表达式 e1、e2、...、eN 的表达式 expr,按以下顺序计算:For an expression expr, which has sub-expressions e1, e2, ..., eN, evaluated in that order:
- 在 e1 开始时, v 的明确赋值状态与 expr 开头的明确赋值状态相同。The definite assignment state of v at the beginning of e1 is the same as the definite assignment state at the beginning of expr.
- 在 ei 开始时, v 的明确赋值状态 (i 大于一个) 与上一个子表达式末尾的明确赋值状态相同。The definite assignment state of v at the beginning of ei (i greater than one) is the same as the definite assignment state at the end of the previous sub-expression.
- 在 expr 结束时, v 的明确赋值状态与 eN 末尾的明确赋值状态相同The definite assignment state of v at the end of expr is the same as the definite assignment state at the end of eN
调用表达式和对象创建表达式Invocation expressions and object creation expressions
对于以下形式的调用表达式 expr :For an invocation expression expr of the form:
primary_expression ( arg1 , arg2 , ... , argN )
或形式的对象创建表达式:or an object creation expression of the form:
new type ( arg1 , arg2 , ... , argN )
- 对于调用表达式,v primary_expression 之前的 v 的明确赋值状态与 expr 前面的 v 的状态相同。For an invocation expression, the definite assignment state of v before primary_expression is the same as the state of v before expr.
- 对于调用表达式,v 之前的 v 的明确赋值状态 与 primary_expression 后 v 的状态相同。For an invocation expression, the definite assignment state of v before arg1 is the same as the state of v after primary_expression.
- 对于对象创建表达式,v 之前的 v 的明确赋值状态 与 expr 前面的 v 的状态相同。For an object creation expression, the definite assignment state of v before arg1 is the same as the state of v before expr.
- 对于每个参数 argi, argi 之后的 v 的明确赋值状态由标准表达式规则确定,忽略任何
ref
或out
修饰符。For each argument argi, the definite assignment state of v after argi is determined by the normal expression rules, ignoring anyref
orout
modifiers. - 对于每 个大于一 的参数 argi , argi 之前的 v 的明确赋值状态与上一个 arg 后 v 的状态相同。For each argument argi for any i greater than one, the definite assignment state of v before argi is the same as the state of v after the previous arg.
- 如果变量 v 作为
out
参数传递 (例如,形式的参数out v
) 在任何参数中,则 expr 后 v 的状态将明确赋值。If the variable v is passed as anout
argument (i.e., an argument of the formout v
) in any of the arguments, then the state of v after expr is definitely assigned. 本来 expr 后 v 的状态与 argN 后 v 的状态相同。Otherwise; the state of v after expr is the same as the state of v after argN. - 对于数组初始值设定项 (数组创建表达式) ,对象初始值设定项 (对象初始值设定 项) ,集合初始值设定项 (集合 初始值设定项) 和匿名对象初始值设定项 (匿名对象创建表达式) ,明确的赋值状态由定义这些构造的扩展确定。For array initializers (Array creation expressions), object initializers (Object initializers), collection initializers (Collection initializers) and anonymous object initializers (Anonymous object creation expressions), the definite assignment state is determined by the expansion that these constructs are defined in terms of.
简单赋值表达式Simple assignment expressions
对于以下形式 的表达式表达式 w = expr_rhs
:For an expression expr of the form w = expr_rhs
:
- 在 expr_rhs 之前, v 的明确赋值状态与 expr 之前的 v 的明确赋值状态相同。The definite assignment state of v before expr_rhs is the same as the definite assignment state of v before expr.
- Expr 后 v 的明确赋值状态由确定:The definite assignment state of v after expr is determined by:
- 如果 w 是与 v 相同的变量,则 expr 后 v 的明确赋值状态是明确赋值的。If w is the same variable as v, then the definite assignment state of v after expr is definitely assigned.
- 否则,如果在结构类型的实例构造函数中发生分配,则如果 w 是属性访问,该属性访问在正在构造的实例上指定了自动实现的属性 P ,而 v 是 P 的隐藏支持字段,则 expr 后 v 的明确赋值状态为明确赋值。Otherwise, if the assignment occurs within the instance constructor of a struct type, if w is a property access designating an automatically implemented property P on the instance being constructed and v is the hidden backing field of P, then the definite assignment state of v after expr is definitely assigned.
- 否则,在 expr 后, v 的明确赋值状态与 expr_rhs 后 v 的明确分配状态相同。Otherwise, the definite assignment state of v after expr is the same as the definite assignment state of v after expr_rhs.
&& (条件和) 表达式&& (conditional AND) expressions
对于以下形式 的表达式表达式 expr_first && expr_second
:For an expression expr of the form expr_first && expr_second
:
- 在 expr_first 之前, v 的明确赋值状态与 expr 之前的 v 的明确赋值状态相同。The definite assignment state of v before expr_first is the same as the definite assignment state of v before expr.
- 如果 expr_first 的 v 状态为明确赋值或 "在 true 表达式后明确赋值",则在 expr_second 之前, v 的明确赋值状态为明确赋值。The definite assignment state of v before expr_second is definitely assigned if the state of v after expr_first is either definitely assigned or "definitely assigned after true expression". 否则,不会明确赋值。Otherwise, it is not definitely assigned.
- Expr 后 v 的明确赋值状态由确定:The definite assignment state of v after expr is determined by:
- 如果 expr_first 是具有值的常量表达式,则在
false
expr 后 v 的明确赋值状态与 expr_first 后 v 的明确赋值状态相同。If expr_first is a constant expression with the valuefalse
, then the definite assignment state of v after expr is the same as the definite assignment state of v after expr_first. - 否则,如果在 expr_first 后 v 的状态为明确赋值,则 expr 后 v 的状态将明确赋值。Otherwise, if the state of v after expr_first is definitely assigned, then the state of v after expr is definitely assigned.
- 否则,如果在 expr_second 后 ,v 的状态是明确赋值的,并且 expr_first 后 v 的状态是 "在 false 表达式后明确赋值",则 expr 后 v 的状态将明确赋值。Otherwise, if the state of v after expr_second is definitely assigned, and the state of v after expr_first is "definitely assigned after false expression", then the state of v after expr is definitely assigned.
- 否则,如果在 expr_second 后 v 的状态是明确赋值的或 "在 true 表达式后明确赋值",则 expr 后 v 的状态为 "在 true 表达式后明确赋值"。Otherwise, if the state of v after expr_second is definitely assigned or "definitely assigned after true expression", then the state of v after expr is "definitely assigned after true expression".
- 否则,如果 " v " expr_first 后面的 "v" 的状态为 "在假表达式后明确赋值",并且在 expr_second 后 v 的状态为 "在假表达式后明确赋值",则 expr 后 v 的状态为 "在假表达式后明确赋值"。Otherwise, if the state of v after expr_first is "definitely assigned after false expression", and the state of v after expr_second is "definitely assigned after false expression", then the state of v after expr is "definitely assigned after false expression".
- 否则,不明确赋值 expr 后的 v 状态。Otherwise, the state of v after expr is not definitely assigned.
- 如果 expr_first 是具有值的常量表达式,则在
示例中In the example
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
而不是在另一个语句中),该变量被视为已明确赋值。the variable i
is considered definitely assigned in one of the embedded statements of an if
statement but not in the other. 在 if
方法的语句中 F
,变量在 i
第一个嵌入语句中是明确赋值的,因为在执行 (i = y)
此嵌入语句之前,表达式的执行始终为。In the if
statement in method F
, the variable i
is definitely assigned in the first embedded statement because execution of the expression (i = y)
always precedes execution of this embedded statement. 与此相反, i
第二个嵌入语句中的变量并不是明确赋值的,因为 x >= 0
可能已对 false 进行了测试,导致变量 i
未赋值。In contrast, the variable i
is not definitely assigned in the second embedded statement, since x >= 0
might have tested false, resulting in the variable i
being unassigned.
|| (条件表达式或) 表达式|| (conditional OR) expressions
对于以下形式 的表达式表达式 expr_first || expr_second
:For an expression expr of the form expr_first || expr_second
:
- 在 expr_first 之前, v 的明确赋值状态与 expr 之前的 v 的明确赋值状态相同。The definite assignment state of v before expr_first is the same as the definite assignment state of v before expr.
- 如果 expr_first 的 v 状态为明确赋值或 "在 false 表达式后明确赋值",则在 expr_second 之前, v 的明确赋值状态为明确赋值。The definite assignment state of v before expr_second is definitely assigned if the state of v after expr_first is either definitely assigned or "definitely assigned after false expression". 否则,不会明确赋值。Otherwise, it is not definitely assigned.
- Expr 后的 v 的明确赋值语句由确定:The definite assignment statement of v after expr is determined by:
- 如果 expr_first 是具有值的常量表达式,则在
true
expr 后 v 的明确赋值状态与 expr_first 后 v 的明确赋值状态相同。If expr_first is a constant expression with the valuetrue
, then the definite assignment state of v after expr is the same as the definite assignment state of v after expr_first. - 否则,如果在 expr_first 后 v 的状态为明确赋值,则 expr 后 v 的状态将明确赋值。Otherwise, if the state of v after expr_first is definitely assigned, then the state of v after expr is definitely assigned.
- 否则,如果在 expr_second 后 ,v 的状态是明确赋值的,并且 expr_first 后 v 的状态是 "在 true 表达式后明确赋值",则 expr 后 v 的状态将明确赋值。Otherwise, if the state of v after expr_second is definitely assigned, and the state of v after expr_first is "definitely assigned after true expression", then the state of v after expr is definitely assigned.
- 否则,如果在 expr_second 后 v 的状态是明确赋值的或 "在假表达式后明确赋值",则 expr 后 v 的状态为 "在假表达式后明确赋值"。Otherwise, if the state of v after expr_second is definitely assigned or "definitely assigned after false expression", then the state of v after expr is "definitely assigned after false expression".
- 否则,如果在 expr_first 后 的 v 状态是 "在 true 表达式后明确赋值",并且在 expr_second 后 v 的状态为 "在 true 表达式后明确赋值",则 expr 后 v 的状态为 "在 true 表达式后明确赋值"。Otherwise, if the state of v after expr_first is "definitely assigned after true expression", and the state of v after expr_second is "definitely assigned after true expression", then the state of v after expr is "definitely assigned after true expression".
- 否则,不明确赋值 expr 后的 v 状态。Otherwise, the state of v after expr is not definitely assigned.
- 如果 expr_first 是具有值的常量表达式,则在
示例中In the example
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
而不是在另一个语句中),该变量被视为已明确赋值。the variable i
is considered definitely assigned in one of the embedded statements of an if
statement but not in the other. 在 if
方法的语句中 G
,变量在 i
第二个嵌入语句中是明确赋值的,因为在执行 (i = y)
此嵌入语句之前,表达式的执行始终为。In the if
statement in method G
, the variable i
is definitely assigned in the second embedded statement because execution of the expression (i = y)
always precedes execution of this embedded statement. 与此相反, i
第一个嵌入语句中的变量不是明确赋值的,因为 x >= 0
可能测试了 true,导致变量 i
被分配。In contrast, the variable i
is not definitely assigned in the first embedded statement, since x >= 0
might have tested true, resulting in the variable i
being unassigned.
!! (逻辑求反) 表达式(logical negation) expressions
对于以下形式 的表达式表达式 ! expr_operand
:For an expression expr of the form ! expr_operand
:
- 在 expr_operand 之前, v 的明确赋值状态与 expr 之前的 v 的明确赋值状态相同。The definite assignment state of v before expr_operand is the same as the definite assignment state of v before expr.
- Expr 后 v 的明确赋值状态由确定:The definite assignment state of v after expr is determined by:
- 如果在 * expr_operand * 之后的 v 状态为明确赋值,则 expr 后 v 的状态将明确赋值。If the state of v after *expr_operand *is definitely assigned, then the state of v after expr is definitely assigned.
- 如果未明确赋值 * expr_operand * 之后的 v 状态,则不明确赋值 expr 后的 v 状态。If the state of v after *expr_operand *is not definitely assigned, then the state of v after expr is not definitely assigned.
- 如果在 * expr_operand * 之后的 v 状态是 "在假表达式后明确赋值",则 expr 后 v 的状态为 "在 true 表达式后明确赋值"。If the state of v after *expr_operand *is "definitely assigned after false expression", then the state of v after expr is "definitely assigned after true expression".
- 如果在 * expr_operand * 之后的 v 状态是 "在 true 表达式后明确赋值",则 expr 后 v 的状态为 "在假表达式后明确赋值"。If the state of v after *expr_operand *is "definitely assigned after true expression", then the state of v after expr is "definitely assigned after false expression".
???? ) 表达式 (空合并(null coalescing) expressions
对于以下形式 的表达式表达式 expr_first ?? expr_second
:For an expression expr of the form expr_first ?? expr_second
:
- 在 expr_first 之前, v 的明确赋值状态与 expr 之前的 v 的明确赋值状态相同。The definite assignment state of v before expr_first is the same as the definite assignment state of v before expr.
- 在 expr_second 之前, v 的明确赋值状态与 expr_first 后 v 的明确分配状态相同。The definite assignment state of v before expr_second is the same as the definite assignment state of v after expr_first.
- Expr 后的 v 的明确赋值语句由确定:The definite assignment statement of v after expr is determined by:
- 如果 expr_first 是常量表达式 (使用值为 Null 的 常量) 表达式,则 expr 后 v 的状态与 expr_second 后 v 的状态相同。If expr_first is a constant expression (Constant expressions) with value null, then the state of v after expr is the same as the state of v after expr_second.
- 否则, expr 后面的 v 状态与 expr_first 后 v 的明确分配状态相同。Otherwise, the state of v after expr is the same as the definite assignment state of v after expr_first.
?: (条件) 表达式?: (conditional) expressions
对于以下形式 的表达式表达式 expr_cond ? expr_true : expr_false
:For an expression expr of the form expr_cond ? expr_true : expr_false
:
- 在 expr_cond 之前, v 的明确赋值状态与 expr 前面的 v 的状态相同。The definite assignment state of v before expr_cond is the same as the state of v before expr.
- 当且仅当以下其中一项保留时,v expr_true 前 v 的明确赋值状态是明确赋值的:The definite assignment state of v before expr_true is definitely assigned if and only if one of the following holds:
- expr_cond 是具有值的常量表达式
false
expr_cond is a constant expression with the valuefalse
- expr_cond 的状态 为明确 赋值或 "true expression 之后明确赋值"。the state of v after expr_cond is definitely assigned or "definitely assigned after true expression".
- expr_cond 是具有值的常量表达式
- 当且仅当以下其中一项保留时,v expr_false 前 v 的明确赋值状态是明确赋值的:The definite assignment state of v before expr_false is definitely assigned if and only if one of the following holds:
- expr_cond 是具有值的常量表达式
true
expr_cond is a constant expression with the valuetrue
- expr_cond 的状态为明确赋值或 "在 false 表达式后明确赋值"。the state of v after expr_cond is definitely assigned or "definitely assigned after false expression".
- expr_cond 是具有值的常量表达式
- Expr 后 v 的明确赋值状态由确定:The definite assignment state of v after expr is determined by:
- 如果 expr_cond 是常量表达式 (常数表达式) 值,
true
则 expr 后 v 的状态与 expr_true 后 v 的状态相同。If expr_cond is a constant expression (Constant expressions) with valuetrue
then the state of v after expr is the same as the state of v after expr_true. - 否则,如果 expr_cond 是常量表达式 (常数表达式) 值,
false
则 expr 后 v 的状态与 expr_false 后 v 的状态相同。Otherwise, if expr_cond is a constant expression (Constant expressions) with valuefalse
then the state of v after expr is the same as the state of v after expr_false. - 否则,如果在 expr_true 后, v 的状态为明确分配,并且 expr_false 的状态 为明确赋值,则 expr 后 v 的状态将明确赋值。 Otherwise, if the state of v after expr_true is definitely assigned and the state of v after expr_false is definitely assigned, then the state of v after expr is definitely assigned.
- 否则,不明确赋值 expr 后的 v 状态。Otherwise, the state of v after expr is not definitely assigned.
- 如果 expr_cond 是常量表达式 (常数表达式) 值,
匿名函数Anonymous functions
对于 lambda_expression 或带有正文的 anonymous_method_expression expr (块 或 表达式) 体:For a lambda_expression or anonymous_method_expression expr with a body (either block or expression) body:
- 在 body 之前,外部变量 v 的明确赋值状态与 expr 前面的 v 的状态相同。The definite assignment state of an outer variable v before body is the same as the state of v before expr. 也就是说,外部变量的明确赋值状态是从匿名函数的上下文继承而来的。That is, definite assignment state of outer variables is inherited from the context of the anonymous function.
- Expr 后面的外部变量 v 的明确赋值状态与 expr 前面的 v 的状态相同。The definite assignment state of an outer variable v after expr is the same as the state of v before expr.
示例The example
delegate bool Filter(int i);
void F() {
int max;
// Error, max is not definitely assigned
Filter f = (int n) => n < max;
max = 5;
DoWork(f);
}
生成编译时错误,因为在 max
声明匿名函数的位置未明确赋值。generates a compile-time error since max
is not definitely assigned where the anonymous function is declared. 示例The example
delegate void D();
void F() {
int n;
D d = () => { n = 1; };
d();
// Error, n is not definitely assigned
Console.WriteLine(n);
}
还会生成编译时错误,因为对 n
匿名函数的赋值不会影响匿名函数之外的明确赋值状态 n
。also generates a compile-time error since the assignment to n
in the anonymous function has no affect on the definite assignment state of n
outside the anonymous function.
变量引用Variable references
Variable_reference 是分类为变量的 表达式。A variable_reference is an expression that is classified as a variable. Variable_reference 表示可访问的存储位置以提取当前值并存储新值。A variable_reference denotes a storage location that can be accessed both to fetch the current value and to store a new value.
variable_reference
: expression
;
在 C 和 c + + 中, variable_reference 称为 lvalue。In C and C++, a variable_reference is known as an lvalue.
变量引用的原子性Atomicity of variable references
以下数据类型的读取和写入是原子的:、、、、、、、、 bool
char
byte
sbyte
short
ushort
uint
int
float
和引用类型。Reads and writes of the following data types are atomic: bool
, char
, byte
, sbyte
, short
, ushort
, uint
, int
, float
, and reference types. 此外,在前面的列表中,具有基础类型的枚举类型的读取和写入也是原子的。In addition, reads and writes of enum types with an underlying type in the previous list are also atomic. 其他类型(包括 long
、 ulong
、 double
、以及 decimal
用户定义类型)的读取和写入不能保证为原子性。Reads and writes of other types, including long
, ulong
, double
, and decimal
, as well as user-defined types, are not guaranteed to be atomic. 除了为此目的而设计的库函数外,不保证原子读修改写入,如递增或递减。Aside from the library functions designed for that purpose, there is no guarantee of atomic read-modify-write, such as in the case of increment or decrement.