變數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 ,是一個c值參數b ,是一個參考參數,是一個輸出參數, 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.

結構之執行個體變數的初始指派狀態與包含 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

未使用refout修飾詞宣告的參數是值參數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. 不過,如果值參數是由匿名函式(匿名函式運算式)所捕捉,則其存留時間至少會延伸到從該匿名函式建立的委派或運算式樹狀結構符合垃圾收集的資格。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修飾詞宣告的參數是output 參數A parameter declared with an out modifier is an output parameter.

輸出參數不會建立新的儲存位置。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. 因此,輸出參數的值一律與基礎變數相同。Thus, the value of an output parameter is always the same as the underlying variable.

下列明確指派規則適用于輸出參數。The following definite assignment rules apply to output parameters. 請注意參考參數中所述參考參數的不同規則。Note the different rules for reference parameters described in Reference parameters.

  • 變數不需要明確指派,就可以在函式成員或委派調用中傳遞做為輸出參數。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.
  • 在函數成員或匿名函式內,會將輸出參數視為一開始未指派。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_statementswitch_statementusing_statement中。或是由try_statementforeach_statementspecific_catch_clauseA 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. 此存留期至少會從 entry 延伸到區塊for_statementswitch_statementusing_statementforeach_statement或與其關聯的specific_catch_clause ,直到該區塊for_statementswitch_statementusing_statementforeach_statementspecific_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_statementswitch_statementusing_statementforeach_statementspecific_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_statementswitch_statementusing_statementforeach_statementspecific_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_statementspecific_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的變數,預設值為nullFor a variable of a reference_type, the default value is null.

預設值的初始化通常是藉由讓記憶體管理員或垃圾收集行程將記憶體初始化為全位-零,再配置給使用。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. 基於這個理由,使用全位-零來代表 null 參考是很方便的。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:

最初指派的變數、一開始未指派的變數,以及判斷明確指派的精確規則中,會描述上述非正式規則的基礎正式規格。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,
    • 變數會當做輸出參數傳遞,或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 a return 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.
  • Struct_type 實例的函式的變數必須在該實例的函式傳回的每個位置明確指派。thisThe this 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 a catch clause or a foreach 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 the this variable of struct instance constructors.
  • 區域變數,但catch子句foreach或語句中所宣告的變數除外。Local variables, except those declared in a catch clause or a foreach 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
  • 在將控制項傳輸至另一個語句或語句結束點的每個 arc 上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. 這表示在此點的所有可能控制流程上,已將值指派給vThis 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 type bool, 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是在所有此類控制流程傳輸上明確指派,則會在語句的開頭明確指派vIf (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).
  • Vchecked區塊、 、、lockif 、、、、do、或的結束點的明確指派狀態。 while unchecked for foreach 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, or switch 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 ,則會在語句的結束點明確指派vIf 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的明確指派狀態會傳送到區塊中語句清單的第一個語句(如果語句清單是空的,則為該區塊的結束點),這與區塊前面的明確指派語句相同。、 checkedunchecked語句。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

針對運算式語句包含運算式exprstmtFor an expression statement stmt that consists of the expression expr:

  • vexpr開頭具有相同的明確指派狀態,如同在stmt開頭。v has the same definite assignment state at the beginning of expr as at the beginning of stmt.
  • 如果v是在expr結尾明確指派,則會在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的明確指派狀態會決定為語句清單,每個具有初始化運算式的宣告都有一個指派語句(順序為宣告)。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
  • vexpr開頭具有相同的明確指派狀態,如同在stmt開頭。v has the same definite assignment state at the beginning of expr as at the beginning of stmt.
  • 如果在expr的結尾明確指派v ,則在控制流程傳輸至then_stmt ,以及如果沒有 else子句時, 會將它明確指派給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.
  • 如果vexpr結尾處的「true expression 之後明確指派」狀態,則會在控制流程傳輸至then_stmt時明確指派,而不會在控制流程傳輸上明確指派給任一else_stmt ,或如果沒有 else 子句,則為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.
  • 如果vexpr結尾處具有「在 false 運算式之後明確指派」狀態,則會在控制流程傳送至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.
  • 否則 ,如果沒有else 子句,則會將v視為不會在控制流程傳輸到then_stmtelse_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

在具有控制運算式expr的語句stmtswitch中:In a switch statement stmt with a controlling expression expr:

  • Vexpr開頭的明確指派狀態,與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.
  • 在控制流程上的v明確指派狀態傳送至可連線的 switch block 語句清單,與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
  • vexpr開頭具有相同的明確指派狀態,如同在stmt開頭。v has the same definite assignment state at the beginning of expr as at the beginning of stmt.
  • 如果在expr結尾明確指派v ,則會在控制流程傳輸上明確指派給while_bodystmt的結束點。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.
  • 如果vexpr結尾處的「true expression 之後明確指派」狀態,則會在控制流程傳送至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.
  • 如果vexpr結尾處具有「在 false 運算式之後明確指派」狀態,則會在控制流程傳輸到stmt的結束點時明確指派,但不會在控制流程傳輸上明確指派 _bodyIf 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 ) ;
  • v在控制流程上具有相同的明確指派狀態,從stmt開頭到do_body ,如同在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.
  • vexpr的開頭具有相同的明確指派狀態,如同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.
  • 如果vexpr結尾處具有「在 false 運算式之後明確指派」狀態,則會在控制流程傳輸上,將它明確指派給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 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語句中省略了for_condition ,則評估明確的指派會繼續進行,如同上述擴充true中的 for_condition 已被取代。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

break在、或continue 語句goto所造成的控制流程傳輸上,v 的明確指派狀態,與語句開頭的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 ;

Vexpr開頭的明確指派狀態,與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 ;
  • Vexpr開頭的明確指派狀態,與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是輸出參數,則必須明確地指派其中一個:If v is an output parameter, then it must be definitely assigned either:
    • after expr之後after expr
    • 或,位於括finallytry語句- try之或finally 的區塊-結尾。 catch - finally returnor at the end of the finally block of a try-finally or try-catch-finally that encloses the return statement.

針對格式為的語句 stmt:For a statement stmt of the form:

return ;
  • 如果v是輸出參數,則必須明確地指派其中一個:If v is an output parameter, then it must be definitely assigned either:
    • stmt之前before stmt
    • 或,位於括finallytry語句- try之或finally 的區塊-結尾。 catch - finally returnor at the end of the finally block of a try-finally or try-catch-finally that encloses the return statement.

Try-catch 語句Try-catch statements

針對格式為的語句stmtFor a statement stmt of the form:

try try_block
catch(...) catch_block_1
...
catch(...) catch_block_n
  • Vtry_block開頭的明確指派狀態,與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.
  • Vcatch_block_i開頭的明確指派狀態(適用于任何i)與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.
  • 如果在try_block的端點和每個catch_block_i (針對每個i從1到 n)明確指派v ,則會明確指派vstmt結束點的明確指派狀態。 ).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-finally 語句Try-finally statements

針對格式為的語句try stmt:For a try statement stmt of the form:

try try_block finally finally_block
  • Vtry_block開頭的明確指派狀態,與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.
  • Vfinally_block開頭的明確指派狀態,與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.
  • 只有在下列其中一項條件成立時,才會明確指派vstmt結束點的明確指派狀態: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:
    • vtry_block的端點明確指派v is definitely assigned at the end-point of try_block
    • vfinally_block的端點明確指派v is definitely assigned at the end-point of finally_block

如果在 try_block 內開始進行控制流程傳輸( goto例如,語句),並在 try_block之外結束,則如果v為,則也會將v視為明確指派給該控制流程傳輸明確指派于finally_block的端點。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 -語句的語句:catchis 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
  • Vexpr開頭的明確指派狀態,與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.
  • V在控制流程傳輸到embedded_statementstmt結束點的明確指派狀態,與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 語句Using statements

針對格式為的語句using stmt:For a using statement stmt of the form:

using ( resource_acquisition ) embedded_statement
  • Vresource_acquisition開頭的明確指派狀態,與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
  • Vexpr開頭的明確指派狀態,與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 ;
  • Vexpr開頭的明確指派狀態,與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.
  • Vstmt結尾的明確指派狀態,與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語句對明確的指派狀態不會有任何影響。A yield 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

下列規則適用于這類運算式:括號運算式(括號運算式)、元素存取運算式(專案存取)、具有索引編制的基底存取運算式(基底存取)、遞增和遞減運算式(後置遞增和遞減運算子前置遞增和遞減運算子)、cast 運算式(cast 運算式)、 +一元-~*、運算式,binary + -*, ,,/,,,,,,, ,,,,>=,,,, % << >> < <= >``==、 、、is^ 、、運算式(算術運算子移位運算子、關聯式和類型測試) | as != & 運算子邏輯運算子)、複合指派運算式(複合 checked指派)和unchecked運算式(checked 和 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.
  • Vei開頭的明確指派狀態(i大於1)與前一個子運算式結尾的明確指派狀態相同。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.
  • Vexpr結尾的明確指派狀態,與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

針對格式為的調用運算式exprFor 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明確指派狀態與expr**之前的狀態相同。For an invocation expression, the definite assignment state of v before primary_expression is the same as the state of v before expr.
  • 針對叫用運算式, v的明確指派狀態在arg1之前,會與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.
  • 若為物件建立運算式,則在 arg1前面的明確指派狀態會與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的明確指派狀態是由一般運算式規則所決定refout忽略任何或修飾詞。For each argument argi, the definite assignment state of v after argi is determined by the normal expression rules, ignoring any ref or out modifiers.
  • 針對任何i大於1的每個引數argivargi之前的明確指派狀態與上一個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的引數),則會明確指派vexpr之後的狀態。If the variable v is passed as an out argument (i.e., an argument of the form out v) in any of the arguments, then the state of v after expr is definitely assigned. 別的v after expr的狀態與 ...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為的運算式exprFor an expression expr of the form w = expr_rhs:

  • Vexpr_rhs之前的明確指派狀態,與expr**前面的明確指派狀態相同。The definite assignment state of v before expr_rhs is the same as the definite assignment state of v before expr.
  • V after expr之後的明確指派狀態取決於:The definite assignment state of v after expr is determined by:
    • 如果wv是相同的變數,則會明確指派v after expr之後的明確指派狀態。If w is the same variable as v, then the definite assignment state of v after expr is definitely assigned.
    • 否則,如果指派發生在結構型別的實例函式中,則如果w是屬性存取,在所建立的實例上指定自動實作為屬性P ,而v是的隱藏支援欄位P,則會明確指派v after expr之後的明確指派狀態。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.
    • 否則, v after expr之後的明確指派狀態,會與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為的運算式exprFor an expression expr of the form expr_first && expr_second:

  • Vexpr_first之前的明確指派狀態,與expr**前面的明確指派狀態相同。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 的明確指派狀態會明確指派。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.
  • V after expr之後的明確指派狀態取決於:The definite assignment state of v after expr is determined by:
    • 如果expr_first是具有值false的常數運算式,則v after expr的明確指派狀態會與expr_first之後的v明確指派狀態相同。If expr_first is a constant expression with the value false, then the definite assignment state of v after expr is the same as the definite assignment state of v after expr_first.
    • 否則,如果已明確指派expr_firstv的狀態,則會將v的狀態明確指派給exprOtherwise, if the state of v after expr_first is definitely assigned, then the state of v after expr is definitely assigned.
    • 否則,如果已明確指派expr_secondv的狀態,且expr_first之後的v狀態是「在 false 運算式之後明確指派」,則v的狀態一定會是expr指派.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".
    • 否則,如果expr_first之後的v狀態是「在 false 運算式之後明確指派」,而且expr_second之後的v狀態是「在 false 運算式之後明確指派」,則v的狀態會在之後expr是「在 false 運算式之後明確指派」。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.

在範例中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為的運算式exprFor an expression expr of the form expr_first || expr_second:

  • Vexpr_first之前的明確指派狀態,與expr**前面的明確指派狀態相同。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之前的明確指派狀態是明確指派的。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.
  • V after運算式的明確指派語句取決於:The definite assignment statement of v after expr is determined by:
    • 如果expr_first是具有值true的常數運算式,則v after expr的明確指派狀態會與expr_first之後的v明確指派狀態相同。If expr_first is a constant expression with the value true, then the definite assignment state of v after expr is the same as the definite assignment state of v after expr_first.
    • 否則,如果已明確指派expr_firstv的狀態,則會將v的狀態明確指派給exprOtherwise, if the state of v after expr_first is definitely assigned, then the state of v after expr is definitely assigned.
    • 否則,如果已明確指派expr_secondv的狀態,且expr_first之後的v狀態是「在 true 運算式之後明確指派」,則v的狀態一定會是expr指派.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狀態,或「在 false 運算式之後明確指派」,則v after expr後面的狀態會是「在 false 運算式之後明確指派」。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_firstv的狀態是「在 true 運算式之後明確指派」,而且expr_second之後的v狀態是「在 true 運算式之後明確指派」,則v的狀態會在expr 之後是「在 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.

在範例中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為的運算式exprFor an expression expr of the form ! expr_operand:

  • Vexpr_operand之前的明確指派狀態,與expr**前面的明確指派狀態相同。The definite assignment state of v before expr_operand is the same as the definite assignment state of v before expr.
  • V after expr之後的明確指派狀態取決於:The definite assignment state of v after expr is determined by:
    • 如果 * expr_operand * 之後的v狀態是明確指派的,則會將v的狀態明確指派給expr after。If the state of v after *expr_operand *is definitely assigned, then the state of v after expr is definitely assigned.
    • 如果 * expr_operand * 之後的v狀態未明確指派,則不會明確指派v after expr的狀態。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狀態是「在 false 運算式之後明確指派」,則v after expr後面的狀態會是「在 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 運算式之後明確指派」,則v after expr後面的狀態會是「在 false 運算式之後明確指派」。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 聯合)運算式(null coalescing) expressions

針對格式expr_first ?? expr_second為的運算式exprFor an expression expr of the form expr_first ?? expr_second:

  • Vexpr_first之前的明確指派狀態,與expr**前面的明確指派狀態相同。The definite assignment state of v before expr_first is the same as the definite assignment state of v before expr.
  • Vexpr_second之前的明確指派狀態,與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.
  • V after運算式的明確指派語句取決於:The definite assignment statement of v after expr is determined by:
    • 如果expr_first是具有值 null 的常數運算式(常數運算式),則v after expr的狀態會與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.
  • 否則, v after expr的狀態會與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為的運算式exprFor an expression expr of the form expr_cond ? expr_true : expr_false:

  • Vexpr_cond之前的明確指派狀態,與expr之前的v狀態相同。The definite assignment state of v before expr_cond is the same as the state of v before expr.
  • 只有在下列其中一項保留時,才會明確指派expr_true 的明確指派狀態:The definite assignment state of v before expr_true is definitely assigned if and only if one of the following holds:
    • expr_cond是具有值的常數運算式falseexpr_cond is a constant expression with the value false
    • expr_cond之後的v狀態是明確指派的,或「在 true 運算式之後明確指派」。the state of v after expr_cond is definitely assigned or "definitely assigned after true expression".
  • 只有在下列其中一項保留時,才會明確指派expr_false 的明確指派狀態:The definite assignment state of v before expr_false is definitely assigned if and only if one of the following holds:
    • expr_cond是具有值的常數運算式trueexpr_cond is a constant expression with the value true
  • expr_cond之後的v狀態是明確指派的,或「在 false 運算式之後明確指派」。the state of v after expr_cond is definitely assigned or "definitely assigned after false expression".
  • V after expr之後的明確指派狀態取決於:The definite assignment state of v after expr is determined by:
    • 如果expr_cond是具有值true的常數運算式(常數運算式),則v after expr的狀態會與expr_true之後的v狀態相同。If expr_cond is a constant expression (Constant expressions) with value true then the state of v after expr is the same as the state of v after expr_true.
    • 否則,如果expr_cond是具有值false的常數運算式(常數運算式),則v after expr的狀態會與expr_false之後的v狀態相同。Otherwise, if expr_cond is a constant expression (Constant expressions) with value false then the state of v after expr is the same as the state of v after expr_false.
    • 否則,如果已明確指派expr_truev的狀態,且明確指派expr_false 之後的 v 狀態,則會明確指派v after expr的狀態。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.

匿名函式Anonymous functions

針對具有主體(區塊運算式主體lambda_expressionanonymous_method_expression exprFor a lambda_expression or anonymous_method_expression expr with a body (either block or expression) 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.
  • 外部變數vexpr之後的明確指派狀態,與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稱為值。In C and C++, a variable_reference is known as an lvalue.

變數參考的不可部分完成性Atomicity of variable references

下列資料類型的讀取和寫入是不可部分完成boolcharbytesbyte uintshortushort、、 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. 其他類型的讀取和寫入,包括longulongdoubledecimal,以及使用者定義類型,則不保證是不可部分完成的。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.