# 運算式Expressions

## 運算式分類Expression classifications

• 值。A value. 每個值都有關聯型別。Every value has an associated type.
• 變數。A variable. 每個變數都有相關聯的類型，亦即變數的宣告類型。Every variable has an associated type, namely the declared type of the variable.
• 命名空間。A namespace. 具有此分類的運算式只能出現在member_access的左邊（成員存取）。An expression with this classification can only appear as the left hand side of a member_access (Member access). 在任何其他內容中，分類為命名空間的運算式會導致編譯時期錯誤。In any other context, an expression classified as a namespace causes a compile-time error.
• 類型。A type. 具有此分類的運算式只能顯示為member_access的左邊（成員存取），或做為 as 運算子（as 運算子）的運算元、is 運算子（is 運算子）或 typeof 運算子（typeof 運算子）。An expression with this classification can only appear as the left hand side of a member_access (Member access), or as an operand for the as operator (The as operator), the is operator (The is operator), or the typeof operator (The typeof operator). 在任何其他內容中，分類為類型的運算式會導致編譯時期錯誤。In any other context, an expression classified as a type causes a compile-time error.
• 方法群組，這是由成員查閱（成員查閱）所產生的一組多載方法。A method group, which is a set of overloaded methods resulting from a member lookup (Member lookup). 方法群組可以有相關聯的實例運算式和關聯的類型引數清單。A method group may have an associated instance expression and an associated type argument list. 叫用實例方法時，評估實例運算式的結果會成為 this此存取）所表示的實例。When an instance method is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access). invocation_expression調用運算式）、 delegate_creation_expression委派建立運算式）和 is 運算子的左邊都允許方法群組，而且可以隱含地轉換成相容的委派類型（方法群組轉換）。A method group is permitted in an invocation_expression (Invocation expressions) , a delegate_creation_expression (Delegate creation expressions) and as the left hand side of an is operator, and can be implicitly converted to a compatible delegate type (Method group conversions). 在任何其他內容中，分類為方法群組的運算式會導致編譯時期錯誤。In any other context, an expression classified as a method group causes a compile-time error.
• Null 常值。A null literal. 具有此分類的運算式可以隱含地轉換成參考型別或可為 null 的類型。An expression with this classification can be implicitly converted to a reference type or nullable type.
• 匿名函式。An anonymous function. 具有此分類的運算式可以隱含地轉換成相容的委派類型或運算式樹狀架構類型。An expression with this classification can be implicitly converted to a compatible delegate type or expression tree type.
• 屬性存取。A property access. 每個屬性存取都有相關聯的類型，即屬性的類型。Every property access has an associated type, namely the type of the property. 此外，屬性存取可能會有相關聯的實例運算式。Furthermore, a property access may have an associated instance expression. 叫用實例屬性存取的存取子（getset 區塊）時，評估實例運算式的結果會成為 this 所表示的實例（此存取權）。When an accessor (the get or set block) of an instance property access is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access).
• 事件存取。An event access. 每個事件存取都有相關聯的類型，亦即事件的類型。Every event access has an associated type, namely the type of the event. 此外，事件存取可能會有相關聯的實例運算式。Furthermore, an event access may have an associated instance expression. 事件存取可能會顯示為 +=-= 運算子（事件指派）的左運算元。An event access may appear as the left hand operand of the += and -= operators (Event assignment). 在任何其他內容中，歸類為事件存取的運算式會導致編譯時期錯誤。In any other context, an expression classified as an event access causes a compile-time error.
• 索引子存取。An indexer access. 每個索引子存取都有相關聯的類型，也就是索引子的元素類型。Every indexer access has an associated type, namely the element type of the indexer. 此外，索引子存取具有相關聯的實例運算式和相關聯的引數清單。Furthermore, an indexer access has an associated instance expression and an associated argument list. 叫用索引子存取的存取子（getset 區塊）時，評估實例運算式的結果會成為 this 所表示的實例（此存取權），而評估引數清單的結果會成為調用的參數清單。When an accessor (the get or set block) of an indexer access is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access), and the result of evaluating the argument list becomes the parameter list of the invocation.
• 無。Nothing. 當運算式為傳回型別為 void的方法調用時，就會發生這種情況。This occurs when the expression is an invocation of a method with a return type of void. 分類為沒有任何內容的運算式僅在statement_expressionexpression 語句）的內容中有效。An expression classified as nothing is only valid in the context of a statement_expression (Expression statements).

### 運算式的值Values of expressions

• 變數的值只是目前儲存在變數所識別之儲存位置中的值。The value of a variable is simply the value currently stored in the storage location identified by the variable. 您必須先將變數視為明確指派（明確指派），才能取得其值，否則會發生編譯時期錯誤。A variable must be considered definitely assigned (Definite assignment) before its value can be obtained, or otherwise a compile-time error occurs.
• 屬性存取運算式的值是藉由叫用屬性的get 存取子取得。The value of a property access expression is obtained by invoking the get accessor of the property. 如果屬性沒有get 存取子，就會發生編譯時期錯誤。If the property has no get accessor, a compile-time error occurs. 否則，會執行函式成員調用（動態多載解析的編譯階段檢查），而調用的結果會成為屬性存取運算式的值。Otherwise, a function member invocation (Compile-time checking of dynamic overload resolution) is performed, and the result of the invocation becomes the value of the property access expression.
• 索引子存取運算式的值是藉由叫用索引子的get 存取子取得。The value of an indexer access expression is obtained by invoking the get accessor of the indexer. 如果索引子沒有get 存取子，就會發生編譯時期錯誤。If the indexer has no get accessor, a compile-time error occurs. 否則，會使用與索引子存取運算式相關聯的引數清單來執行函數成員調用（動態多載解析的編譯時間檢查），而叫用的結果會成為索引子存取運算式的值。Otherwise, a function member invocation (Compile-time checking of dynamic overload resolution) is performed with the argument list associated with the indexer access expression, and the result of the invocation becomes the value of the indexer access expression.

## 靜態和動態繫結Static and Dynamic Binding

• 成員存取： e.MMember access: e.M
• 方法調用： e.M(e1, ..., eN)Method invocation: e.M(e1, ..., eN)
• 委派調用：e(e1, ..., eN)Delegate invocation:e(e1, ..., eN)
• 元素存取： e[e1, ..., eN]Element access: e[e1, ..., eN]
• 物件建立： new C(e1, ..., eN)Object creation: new C(e1, ..., eN)
• 多載的一元運算子： +-!~++--truefalseOverloaded unary operators: +, -, !, ~, ++, --, true, false
• 多載的二元運算子： +-*/%&&&|||??^<<>>==!=><>=<=Overloaded binary operators: +, -, *, /, %, &, &&, |, ||, ??, ^, <<, >>, ==,!=, >, <, >=, <=
• 指派運算子： =+=-=*=/=%=&=|=^=<<=>>=Assignment operators: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
• 隱含和明確轉換Implicit and explicit conversions

### 裝訂-時間Binding-time

object  o = 5;
dynamic d = 5;

Console.WriteLine(5);  // static  binding to Console.WriteLine(int)
Console.WriteLine(o);  // static  binding to Console.WriteLine(object)
Console.WriteLine(d);  // dynamic binding to Console.WriteLine(int)


### 組成運算式的類型Types of constituent expressions

• 編譯時間類型 dynamic 的構成運算式會被視為具有運算式在執行時間評估為之實際值的類型。A constituent expression of compile-time type dynamic is considered to have the type of the actual value that the expression evaluates to at runtime
• 其編譯時期型別為型別參數的組成運算式，會被視為具有型別參數在執行時間系結的型別A constituent expression whose compile-time type is a type parameter is considered to have the type which the type parameter is bound to at runtime
• 否則，構成運算式會被視為具有其編譯時期型別。Otherwise the constituent expression is considered to have its compile-time type.

## 運算子Operators

• 一元運算子。Unary operators. 一元運算子會採用一個運算元，並使用前置詞標記法（例如 --x）或後置標記法（例如 x++）。The unary operators take one operand and use either prefix notation (such as --x) or postfix notation (such as x++).
• 二元運算子。Binary operators. 二元運算子接受兩個運算元，並使用中置標記法（例如 x + y）。The binary operators take two operands and all use infix notation (such as x + y).
• 三元運算子。Ternary operator. 只有一個三元運算子，?:，exists;它會採用三個運算元，並使用中置標記法（c ? x : y）。Only one ternary operator, ?:, exists; it takes three operands and uses infix notation (c ? x : y).

### 運算子優先順序和關聯性Operator precedence and associativity

Null 聯合運算子The null coalescing operator Null 聯合Null coalescing ??

• 除了指派運算子和 null 聯合運算子之外，所有二元運算子都是左關聯的，這表示作業是由左至右執行。Except for the assignment operators and the null coalescing operator, all binary operators are left-associative, meaning that operations are performed from left to right. 例如，x + y + z 會判斷值為 (x + y) + zFor example, x + y + z is evaluated as (x + y) + z.
• 指派運算子、null 聯合運算子和條件運算子（?:）都是靠右關聯的，這表示作業是由右至左執行。The assignment operators, the null coalescing operator and the conditional operator (?:) are right-associative, meaning that operations are performed from right to left. 例如，x = y = z 會判斷值為 x = (y = z)For example, x = y = z is evaluated as x = (y = z).

+   -   !   ~   ++   --   true   false


+   -   *   /   %   &   |   ^   <<   >>   ==   !=   >   <   >=   <=


op x operator op(x)
x op operator op(x)
x op y operator op(x,y)

op xx op形式的作業，其中 op 是可多載的一元運算子，而 x 是類型 X的運算式，其處理方式如下：An operation of the form op x or x op, where op is an overloadable unary operator, and x is an expression of type X, is processed as follows:

• X 針對作業 operator op(x) 所提供的候選使用者定義運算子集合，是使用候選使用者定義運算子的規則來決定。The set of candidate user-defined operators provided by X for the operation operator op(x) is determined using the rules of Candidate user-defined operators.
• 如果候選使用者定義的運算子集合不是空的，則這會成為作業的候選運算子集。If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. 否則，預先定義的一元 operator op 實作為，包括其提升的形式，就會成為作業的候選運算子集。Otherwise, the predefined unary operator op implementations, including their lifted forms, become the set of candidate operators for the operation. 指定運算子的預先定義實作為運算子（主要運算式一元運算子）的描述。The predefined implementations of a given operator are specified in the description of the operator (Primary expressions and Unary operators).
• 多載解析的多載解析規則會套用至候選運算子集合，以選取與引數清單 (x)相關的最佳運算子，而這個運算子會成為多載解析程式的結果。The overload resolution rules of Overload resolution are applied to the set of candidate operators to select the best operator with respect to the argument list (x), and this operator becomes the result of the overload resolution process. 如果多載解析無法選取單一最佳運算子，則會發生系結時錯誤。If overload resolution fails to select a single best operator, a binding-time error occurs.

x op y格式的作業，其中 op 是可多載的二元運算子，xX類型的運算式，而 y 是類型 Y的運算式，其處理方式如下：An operation of the form x op y, where op is an overloadable binary operator, x is an expression of type X, and y is an expression of type Y, is processed as follows:

• XY 為作業 operator op(x,y) 所提供的候選使用者定義運算子集合，是由所決定。The set of candidate user-defined operators provided by X and Y for the operation operator op(x,y) is determined. 集合是由 X 所提供的候選運算子和 Y所提供的候選運算子所組成，每一個都是使用候選使用者定義運算子的規則來決定。The set consists of the union of the candidate operators provided by X and the candidate operators provided by Y, each determined using the rules of Candidate user-defined operators. 如果 XY 是相同的類型，或如果 XY 衍生自通用基底類型，則共用候選運算子只會出現在組合的一次。If X and Y are the same type, or if X and Y are derived from a common base type, then shared candidate operators only occur in the combined set once.
• 如果候選使用者定義的運算子集合不是空的，則這會成為作業的候選運算子集。If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. 否則，預先定義的二進位 operator op 的實作為，包括其提升的形式，就會變成作業的候選運算子集。Otherwise, the predefined binary operator op implementations, including their lifted forms, become the set of candidate operators for the operation. 指定運算子的預先定義實作為運算子（透過條件式邏輯運算子算術運算子）的描述。The predefined implementations of a given operator are specified in the description of the operator (Arithmetic operators through Conditional logical operators). 針對預先定義的列舉和委派運算子，唯一會考慮的運算子是由列舉或委派型別所定義，這是其中一個運算元的系結時間型別。For predefined enum and delegate operators, the only operators considered are those defined by an enum or delegate type that is the binding-time type of one of the operands.
• 多載解析的多載解析規則會套用至候選運算子集合，以選取與引數清單 (x,y)相關的最佳運算子，而這個運算子會成為多載解析程式的結果。The overload resolution rules of Overload resolution are applied to the set of candidate operators to select the best operator with respect to the argument list (x,y), and this operator becomes the result of the overload resolution process. 如果多載解析無法選取單一最佳運算子，則會發生系結時錯誤。If overload resolution fails to select a single best operator, a binding-time error occurs.

### 候選使用者定義的運算子Candidate user-defined operators

• 判斷 T0的類型。Determine the type T0. 如果 T 是可為 null 的型別，T0 是它的基礎型別，否則 T0 等於 TIf T is a nullable type, T0 is its underlying type, otherwise T0 is equal to T.
• 針對 T0 中的所有 operator op 宣告，以及這類運算子的所有提升形式，如果至少有一個運算子適用于引數清單 A的（適用的函式成員），則候選運算子集合會包含 T0中所有這類適用的運算子。For all operator op declarations in T0 and all lifted forms of such operators, if at least one operator is applicable (Applicable function member) with respect to the argument list A, then the set of candidate operators consists of all such applicable operators in T0.
• 否則，如果 objectT0，候選運算子的集合就會是空的。Otherwise, if T0 is object, the set of candidate operators is empty.
• 否則，T0 提供的候選運算子集合是 T0的直接基底類別所提供的候選運算子集合; 如果 T0 是類型參數，則為 T0 的有效基底類別。Otherwise, the set of candidate operators provided by T0 is the set of candidate operators provided by the direct base class of T0, or the effective base class of T0 if T0 is a type parameter.

### 數值升級Numeric promotions

int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
float operator *(float x, float y);
double operator *(double x, double y);
decimal operator *(decimal x, decimal y);


#### 二進位數值升級Binary numeric promotions

• 如果任一個運算元的類型 decimal，則會將另一個運算元轉換成類型 decimal，如果另一個運算元的類型是 floatdouble，就會發生系結時錯誤。If either operand is of type decimal, the other operand is converted to type decimal, or a binding-time error occurs if the other operand is of type float or double.
• 否則，如果任一運算元的類型 double，則會將另一個運算元轉換成類型 doubleOtherwise, if either operand is of type double, the other operand is converted to type double.
• 否則，如果任一運算元的類型 float，則會將另一個運算元轉換成類型 floatOtherwise, if either operand is of type float, the other operand is converted to type float.
• 否則，如果任一運算元的類型 ulong，則會將另一個運算元轉換成類型 ulong，如果另一個運算元的類型是 sbyteshortintlong，就會發生系結時錯誤。Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a binding-time error occurs if the other operand is of type sbyte, short, int, or long.
• 否則，如果任一運算元的類型 long，則會將另一個運算元轉換成類型 longOtherwise, if either operand is of type long, the other operand is converted to type long.
• 否則，如果任一運算元的類型是 uint，而另一個運算元的類型是 sbyteshortint，則兩個運算元都會轉換成類型 longOtherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.
• 否則，如果任一運算元的類型 uint，則會將另一個運算元轉換成類型 uintOtherwise, if either operand is of type uint, the other operand is converted to type uint.
• 否則，兩個運算元都會轉換成類型 intOtherwise, both operands are converted to type int.

decimal AddPercent(decimal x, double percent) {
return x * (1.0 + percent / 100.0);
}


decimal AddPercent(decimal x, double percent) {
return x * (decimal)(1.0 + percent / 100.0);
}


### 提升運算子Lifted operators

• 一元運算子的For the unary operators

+  ++  -  --  !  ~


如果運算元和結果類型都是不可為 null 的實數值型別，則會有一種形式的運算子。a lifted form of an operator exists if the operand and result types are both non-nullable value types. 藉由將單一 ? 修飾詞新增至運算元和結果類型，即可建立此提升形式。The lifted form is constructed by adding a single ? modifier to the operand and result types. 如果運算元為 null，則提升運算子會產生 null 值。The lifted operator produces a null value if the operand is null. 否則，提升運算子會解除包裝運算元、套用基礎運算子，並將結果包裝起來。Otherwise, the lifted operator unwraps the operand, applies the underlying operator, and wraps the result.

• 二元運算子For the binary operators

+  -  *  /  %  &  |  ^  <<  >>


如果運算元和結果類型都是不可為 null 的實數值型別，則會有一種形式的運算子。a lifted form of an operator exists if the operand and result types are all non-nullable value types. 藉由將單一 ? 修飾詞加入至每個運算元和結果類型，即可建立此提升格式。The lifted form is constructed by adding a single ? modifier to each operand and result type. 如果一個或兩個運算元都是 null （例外狀況是 bool? 類型的 &| 運算子（如布林邏輯運算子中所述），則提升運算子會產生 null 值。The lifted operator produces a null value if one or both operands are null (an exception being the & and | operators of the bool? type, as described in Boolean logical operators). 否則，提升運算子會解除包裝運算元、套用基礎運算子，並將結果包裝起來。Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.

• 適用于等號比較運算子For the equality operators

==  !=


如果運算元類型既不是可為 null 的實值型別，而且結果型別是 bool，則運算子的一種提升形式存在。a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. 藉由將單一 ? 修飾詞加入至每個運算元類型，即可建立此提升表單。The lifted form is constructed by adding a single ? modifier to each operand type. 提升運算子會將兩個 null 值視為相等，並將 null 值與任何非 null 值不相等。The lifted operator considers two null values equal, and a null value unequal to any non-null value. 如果兩個運算元都不是 null，則提升的運算子會解除包裝運算元並套用基礎運算子，以產生 bool 結果。If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

• 針對關聯式運算子For the relational operators

<  >  <=  >=


如果運算元類型既不是可為 null 的實值型別，而且結果型別是 bool，則運算子的一種提升形式存在。a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. 藉由將單一 ? 修飾詞加入至每個運算元類型，即可建立此提升表單。The lifted form is constructed by adding a single ? modifier to each operand type. 如果一個或兩個運算元都是 null，則提升運算子會產生值 falseThe lifted operator produces the value false if one or both operands are null. 否則，提升運算子會解除包裝運算元並套用基礎運算子，以產生 bool 結果。Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

## 成員查閱Member lookup

• 首先，會決定一組名為 N 的可存取成員：First, a set of accessible members named N is determined:
• 如果 T 是型別參數，則集合會是在指定為 T之主要條件約束或次要條件約束（類型參數條件約束）之每個類型中，名為 N 之可存取成員集合的聯集，以及 object中名為 N 的可存取成員集合。If T is a type parameter, then the set is the union of the sets of accessible members named N in each of the types specified as a primary constraint or secondary constraint (Type parameter constraints) for T, along with the set of accessible members named N in object.
• 否則，此集合是由 T中名為 N 的所有可存取（成員存取）成員所組成，包括繼承的成員和 object中名為 N 的可存取成員。Otherwise, the set consists of all accessible (Member access) members named N in T, including inherited members and the accessible members named N in object. 如果 T 是結構化型別，則會藉由替代類型引數來取得成員集合，如結構化類型的成員中所述。If T is a constructed type, the set of members is obtained by substituting type arguments as described in Members of constructed types. 包含 override 修飾詞的成員會從集合中排除。Members that include an override modifier are excluded from the set.
• 接下來，如果 K 為零，則會移除其宣告包含類型參數的所有巢狀型別。Next, if K is zero, all nested types whose declarations include type parameters are removed. 如果 K 不是零，則會移除具有不同類型參數數目的所有成員。If K is not zero, all members with a different number of type parameters are removed. 請注意，當 K 為零時，不會移除具有型別參數的方法，因為型別推斷進程（型別推斷）可能可以推斷型別引數。Note that when K is zero, methods having type parameters are not removed, since the type inference process (Type inference) might be able to infer the type arguments.
• 接下來，如果叫用該成員，則會從集合中移除所有非invocable的成員。Next, if the member is invoked, all non-invocable members are removed from the set.
• 接下來，會從集合中移除其他成員所隱藏的成員。Next, members that are hidden by other members are removed from the set. 針對集合中的每個成員 S.M，其中 S 是宣告成員 M 的類型，則會套用下列規則：For every member S.M in the set, where S is the type in which the member M is declared, the following rules are applied:
• 如果 M 是常數、欄位、屬性、事件或列舉成員，則會從集合中移除 S 的基底類型中宣告的所有成員。If M is a constant, field, property, event, or enumeration member, then all members declared in a base type of S are removed from the set.
• 如果 M 是類型宣告，則在 S 的基底類型中宣告的所有非類型都會從集合中移除，而且所有具有相同類型 M 參數數目的類型宣告，都會從集合 S 中移除。If M is a type declaration, then all non-types declared in a base type of S are removed from the set, and all type declarations with the same number of type parameters as M declared in a base type of S are removed from the set.
• 如果 M 是方法，則會從集合中移除在 S 的基底類型中宣告的所有非方法成員。If M is a method, then all non-method members declared in a base type of S are removed from the set.
• 接下來，會從集合中移除類別成員所隱藏的介面成員。Next, interface members that are hidden by class members are removed from the set. 只有當 T 是型別參數，而且 T 同時具有 object 的有效基類和非空白的有效介面集（型別參數條件約束）時，這個步驟才會生效。This step only has an effect if T is a type parameter and T has both an effective base class other than object and a non-empty effective interface set (Type parameter constraints). 針對集合中的每個成員 S.M，其中 S 是宣告成員 M 的類型，如果 Sobject以外的類別宣告，則會套用下列規則：For every member S.M in the set, where S is the type in which the member M is declared, the following rules are applied if S is a class declaration other than object:
• 如果 M 是常數、欄位、屬性、事件、列舉成員或類型宣告，則會從集合中移除在介面宣告中宣告的所有成員。If M is a constant, field, property, event, enumeration member, or type declaration, then all members declared in an interface declaration are removed from the set.
• 如果 M 是方法，則會從集合中移除介面宣告中宣告的所有非方法成員，並從集合中移除與在介面宣告中宣告之 M 簽章相同的所有方法。If M is a method, then all non-method members declared in an interface declaration are removed from the set, and all methods with the same signature as M declared in an interface declaration are removed from the set.
• 最後，移除隱藏的成員後，就會決定查閱的結果：Finally, having removed hidden members, the result of the lookup is determined:
• 如果集合是由不是方法的單一成員所組成，則這個成員就是查閱的結果。If the set consists of a single member that is not a method, then this member is the result of the lookup.
• 否則，如果集合僅包含方法，則這個方法群組就是查閱的結果。Otherwise, if the set contains only methods, then this group of methods is the result of the lookup.
• 否則，查閱是不明確的，而且會發生系結時錯誤。Otherwise, the lookup is ambiguous, and a binding-time error occurs.

### 基底類型Base types

• 如果 objectT，則 T 沒有基底類型。If T is object, then T has no base type.
• 如果 Tenum_typeT 的基底類型為 System.EnumSystem.ValueTypeobject的類別類型。If T is an enum_type, the base types of T are the class types System.Enum, System.ValueType, and object.
• 如果 Tstruct_typeT 的基底類型是 System.ValueTypeobject的類別類型。If T is a struct_type, the base types of T are the class types System.ValueType and object.
• 如果 Tclass_typeT 的基底類型是 T的基類，包括類別類型 objectIf T is a class_type, the base types of T are the base classes of T, including the class type object.
• 如果 Tinterface_typeT 的基底類型是 T 的基底介面，而類別類型 objectIf T is an interface_type, the base types of T are the base interfaces of T and the class type object.
• 如果 Tarray_typeT 的基底類型是 System.Arrayobject的類別類型。If T is an array_type, the base types of T are the class types System.Array and object.
• 如果 Tdelegate_typeT 的基底類型是 System.Delegateobject的類別類型。If T is a delegate_type, the base types of T are the class types System.Delegate and object.

## 函數成員Function members

• 方法Methods
• 屬性Properties
• 「事件」Events
• 索引子Indexers
• 使用者定義的運算子User-defined operators
• 實例構造函式Instance constructors
• 靜態建構函式Static constructors
• 解構函式Destructors

T.F(x,y) 會套用多載解析，以選取類別或結構 TF 的最佳方法。Overload resolution is applied to select the best method F in the class or struct T. 如果未 static方法，就會發生系結時錯誤。A binding-time error occurs if the method is not static. 使用引數清單 (x,y)叫用方法。The method is invoked with the argument list (x,y).
e.F(x,y) 會套用多載解析，以在 e類型所提供的類別、結構或介面中選取最佳方法 F。Overload resolution is applied to select the best method F in the class, struct, or interface given by the type of e. 如果 static方法，就會發生系結時錯誤。A binding-time error occurs if the method is static. 使用實例運算式叫用方法 e 和引數清單 (x,y)The method is invoked with the instance expression e and the argument list (x,y).

P = value 包含類別或結構中屬性 Pset 存取子，會使用引數清單 (value)來叫用。The set accessor of the property P in the containing class or struct is invoked with the argument list (value). 如果 P 是唯讀的，就會發生編譯時期錯誤。A compile-time error occurs if P is read-only. 如果未 staticP，則會 this實例運算式。If P is not static, the instance expression is this.
T.P 會叫用類別或結構 TP 屬性（property）的 get 存取子。The get accessor of the property P in the class or struct T is invoked. 如果未 static P，或 P 為僅限寫入，就會發生編譯時期錯誤。A compile-time error occurs if P is not static or if P is write-only.
T.P = value 類別或結構 T 中屬性 Pset 存取子，會以引數清單 (value)叫用。The set accessor of the property P in the class or struct T is invoked with the argument list (value). 如果未 static P，或 P 是唯讀的，就會發生編譯時期錯誤。A compile-time error occurs if P is not static or if P is read-only.
e.P e 的類型所指定之類別、結構或介面中的屬性 P get 存取子，會以實例運算式 e來叫用。The get accessor of the property P in the class, struct, or interface given by the type of e is invoked with the instance expression e. 如果 P staticP 為僅限寫入，則會發生系結時錯誤。A binding-time error occurs if P is static or if P is write-only.
e.P = value e 類型所指定之類別、結構或介面中的屬性 Pset 存取子，會以實例運算式 e 和引數清單 (value)叫用。The set accessor of the property P in the class, struct, or interface given by the type of e is invoked with the instance expression e and the argument list (value). 如果 P staticP 是唯讀的，就會發生系結時錯誤。A binding-time error occurs if P is static or if P is read-only.

E -= value 會叫用包含類別或結構中事件 Eremove 存取子。The remove accessor of the event E in the containing class or struct is invoked. 如果 E 不是靜態的，則會 this實例運算式。If E is not static, the instance expression is this.
T.E += value 會叫用類別或結構 T 中事件 Eadd 存取子。The add accessor of the event E in the class or struct T is invoked. 如果 E 不是靜態的，就會發生系結時錯誤。A binding-time error occurs if E is not static.
T.E -= value 會叫用類別或結構 T 中事件 Eremove 存取子。The remove accessor of the event E in the class or struct T is invoked. 如果 E 不是靜態的，就會發生系結時錯誤。A binding-time error occurs if E is not static.
e.E += value e 的類型所指定之類別、結構或介面中事件 Eadd 存取子，會以實例運算式 e來叫用。The add accessor of the event E in the class, struct, or interface given by the type of e is invoked with the instance expression e. 如果 E 是靜態的，就會發生系結時錯誤。A binding-time error occurs if E is static.
e.E -= value e 的類型所指定之類別、結構或介面中事件 Eremove 存取子，會以實例運算式 e來叫用。The remove accessor of the event E in the class, struct, or interface given by the type of e is invoked with the instance expression e. 如果 E 是靜態的，就會發生系結時錯誤。A binding-time error occurs if E is static.

e[x,y] = value 會套用多載解析，以在 e類型所提供的類別、結構或介面中選取最佳索引子。Overload resolution is applied to select the best indexer in the class, struct, or interface given by the type of e. 索引子的 set 存取子會使用實例運算式來叫用 e 和引數清單 (x,y,value)The set accessor of the indexer is invoked with the instance expression e and the argument list (x,y,value). 如果索引子是唯讀的，就會發生系結時錯誤。A binding-time error occurs if the indexer is read-only.

x + y 會套用多載解析，以在 x 類型和 y所指定的類別或結構中選取最佳的二元運算子。Overload resolution is applied to select the best binary operator in the classes or structs given by the types of x and y. 使用引數清單 (x,y)叫用選取的運算子。The selected operator is invoked with the argument list (x,y).

### 引數清單Argument lists

• 若為實例的構造函式、方法、索引子和委派，引數會指定為argument_list，如下所述。For instance constructors, methods, indexers and delegates, the arguments are specified as an argument_list, as described below. 針對索引子，叫用 set 存取子時，引數清單會另外包含指定為指派運算子之右運算元的運算式。For indexers, when invoking the set accessor, the argument list additionally includes the expression specified as the right operand of the assignment operator.
• 對於屬性而言，當叫用 get 存取子時，引數清單是空的，而且會包含在叫用 set 存取子時，指定為指派運算子右運算元的運算式。For properties, the argument list is empty when invoking the get accessor, and consists of the expression specified as the right operand of the assignment operator when invoking the set accessor.
• 對於事件，引數清單是由指定為 +=-= 運算子右運算元的運算式所組成。For events, the argument list consists of the expression specified as the right operand of the += or -= operator.
• 針對使用者定義的運算子，引數清單是由一元運算子的單一運算元或二元運算子的兩個運算元所組成。For user-defined operators, the argument list consists of the single operand of the unary operator or the two operands of the binary operator.

argument_list
: argument (',' argument)*
;

argument
: argument_name? argument_value
;

argument_name
: identifier ':'
;

argument_value
: expression
| 'ref' variable_reference
| 'out' variable_reference
;


Argument_list由一個或多個引數所組成，並以逗號分隔。An argument_list consists of one or more arguments, separated by commas. 每個引數都包含一個選擇性的argument_name後面接著一個argument_valueEach argument consists of an optional argument_name followed by an argument_value. 具有argument_name引數稱為具名引數，而沒有argument_name 的引數位置引數An argument with an argument_name is referred to as a named argument, whereas an argument without an argument_name is a positional argument. 位置引數會出現在argument_list中的具名引數後面，這是錯誤。It is an error for a positional argument to appear after a named argument in an argument_list.

Argument_value可以採用下列其中一種形式：The argument_value can take one of the following forms:

• 運算式，表示引數會當做值參數（值參數）傳遞。An expression, indicating that the argument is passed as a value parameter (Value parameters).
• 關鍵字 ref 後面接著variable_reference變數參考），表示引數會當做參考參數（參考參數）傳遞。The keyword ref followed by a variable_reference (Variable references), indicating that the argument is passed as a reference parameter (Reference parameters). 必須先明確指派變數（明確指派），才可以將它當做參考參數傳遞。A variable must be definitely assigned (Definite assignment) before it can be passed as a reference parameter. 關鍵字 out 後面接著variable_reference變數參考），表示引數會當做輸出參數（輸出參數）傳遞。The keyword out followed by a variable_reference (Variable references), indicating that the argument is passed as an output parameter (Output parameters). 在將變數當做輸出參數傳遞的函式成員調用之後，會將變數視為明確指派（明確指派）。A variable is considered definitely assigned (Definite assignment) following a function member invocation in which the variable is passed as an output parameter.

#### 對應的參數Corresponding parameters

• 針對在類別中定義的虛擬方法和索引子，會從函式成員的最特定宣告或覆寫中挑選參數清單，從接收者的靜態類型開始，然後搜尋其基類。For virtual methods and indexers defined in classes, the parameter list is picked from the most specific declaration or override of the function member, starting with the static type of the receiver, and searching through its base classes.
• 如果是介面方法和索引子，則會從介面型別開始並搜尋基底介面，以從最特定的成員定義來挑選參數清單。For interface methods and indexers, the parameter list is picked form the most specific definition of the member, starting with the interface type and searching through the base interfaces. 如果找不到唯一的參數清單，則會構造具有無法存取名稱的參數清單，而且不會建立選擇性參數，因此叫用不能使用已命名的參數或省略選擇性的引數。If no unique parameter list is found, a parameter list with inaccessible names and no optional parameters is constructed, so that invocations cannot use named parameters or omit optional arguments.
• 對於部分方法，會使用定義部分方法宣告的參數清單。For partial methods, the parameter list of the defining partial method declaration is used.
• 對於所有其他函式成員和委派，只有一個參數清單，這是使用的一個。For all other function members and delegates there is only a single parameter list, which is the one used.

• 實例（instance）、方法、索引子和委派之argument_list中的引數：Arguments in the argument_list of instance constructors, methods, indexers and delegates:
• 位置引數，在參數清單中的相同位置發生固定參數時，會對應至該參數。A positional argument where a fixed parameter occurs at the same position in the parameter list corresponds to that parameter.
• 具有以其一般格式叫用之參數陣列的函式成員的位置引數，會對應到參數陣列，這必須在參數清單中的相同位置。A positional argument of a function member with a parameter array invoked in its normal form corresponds to the parameter array, which must occur at the same position in the parameter list.
• 函式成員的位置引數，其中包含以其展開格式叫用的參數陣列，其中不會在參數清單中的相同位置發生固定參數，而會對應至參數陣列中的元素。A positional argument of a function member with a parameter array invoked in its expanded form, where no fixed parameter occurs at the same position in the parameter list, corresponds to an element in the parameter array.
• 具名引數會對應至參數清單中相同名稱的參數。A named argument corresponds to the parameter of the same name in the parameter list.
• 針對索引子，叫用 set 存取子時，指定為指派運算子右運算元的運算式會對應到 set 存取子宣告的隱含 value 參數。For indexers, when invoking the set accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit value parameter of the set accessor declaration.
• 對於屬性，當叫用 get 存取子時，不會有任何引數。For properties, when invoking the get accessor there are no arguments. 叫用 set 存取子時，指定為指派運算子右運算元的運算式會對應到 set 存取子宣告的隱含 value 參數。When invoking the set accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit value parameter of the set accessor declaration.
• 若為使用者定義的一元運算子（包括轉換），單一運算元會對應至運算子宣告的單一參數。For user-defined unary operators (including conversions), the single operand corresponds to the single parameter of the operator declaration.
• 若為使用者定義的二進位運算子，左邊的運算元會對應到第一個參數，右運算元則對應至運算子宣告的第二個參數。For user-defined binary operators, the left operand corresponds to the first parameter, and the right operand corresponds to the second parameter of the operator declaration.

#### 引數清單的執行時間評估Run-time evaluation of argument lists

• 針對值參數，會評估引數運算式，並執行對應參數類型的隱含轉換（隱含轉換）。For a value parameter, the argument expression is evaluated and an implicit conversion (Implicit conversions) to the corresponding parameter type is performed. 產生的值會變成函數成員調用中 value 參數的初始值。The resulting value becomes the initial value of the value parameter in the function member invocation.
• 針對參考或輸出參數，會評估變數參考，而產生的儲存位置會變成函式成員調用中的參數所代表的儲存位置。For a reference or output parameter, the variable reference is evaluated and the resulting storage location becomes the storage location represented by the parameter in the function member invocation. 如果當做參考或輸出參數提供的變數參考是reference_type的陣列元素，則會執行執行時間檢查，以確保陣列的元素類型與參數的類型相同。If the variable reference given as a reference or output parameter is an array element of a reference_type, a run-time check is performed to ensure that the element type of the array is identical to the type of the parameter. 如果此檢查失敗，則會擲回 System.ArrayTypeMismatchExceptionIf this check fails, a System.ArrayTypeMismatchException is thrown.

• 以一般格式叫用具有參數陣列的函式成員時，為參數陣列提供的引數必須是可隱含轉換（隱含轉換）為參數陣列類型的單一運算式。When a function member with a parameter array is invoked in its normal form, the argument given for the parameter array must be a single expression that is implicitly convertible (Implicit conversions) to the parameter array type. 在此情況下，參數陣列的作用會與值參數完全相同。In this case, the parameter array acts precisely like a value parameter.
• 以擴充的形式叫用具有參數陣列的函式成員時，叫用必須為參數陣列指定零或多個位置引數，其中每個引數都是可隱含轉換（隱含轉換）為參數陣列之元素類型的運算式。When a function member with a parameter array is invoked in its expanded form, the invocation must specify zero or more positional arguments for the parameter array, where each argument is an expression that is implicitly convertible (Implicit conversions) to the element type of the parameter array. 在此情況下，調用會使用對應引數數目的長度來建立參數陣列類型的實例、使用指定的引數值初始化陣列實例的元素，並使用新建立的陣列實例作為實際的引數.In this case, the invocation creates an instance of the parameter array type with a length corresponding to the number of arguments, initializes the elements of the array instance with the given argument values, and uses the newly created array instance as the actual argument.

class Test
{
static void F(int x, int y = -1, int z = -2) {
System.Console.WriteLine("x = {0}, y = {1}, z = {2}", x, y, z);
}

static void Main() {
int i = 0;
F(i++, i++, i++);
F(z: i++, x: i++);
}
}


x = 0, y = 1, z = 2
x = 4, y = -1, z = 3


class Test
{
static void F(ref object x) {...}

static void Main() {
object[] a = new object[10];
object[] b = new string[10];
F(ref a[0]);        // Ok
F(ref b[1]);        // ArrayTypeMismatchException
}
}


F 的第二個調用會導致 System.ArrayTypeMismatchException 擲回，因為 b 的實際元素類型是 string 而不是 objectthe second invocation of F causes a System.ArrayTypeMismatchException to be thrown because the actual element type of b is string and not object.

void F(int x, int y, params object[] args);


F(10, 20);
F(10, 20, 30, 40);
F(10, 20, 1, "hello", 3.0);


F(10, 20, new object[] {});
F(10, 20, new object[] {30, 40});
F(10, 20, new object[] {1, "hello", 3.0});


### 型別推斷Type inference

class Chooser
{
static Random rand = new Random();

public static T Choose<T>(T first, T second) {
return (rand.Next(2) == 0)? first: second;
}
}


int i = Chooser.Choose(5, 213);                 // Calls Choose<int>

string s = Chooser.Choose("foo", "bar");        // Calls Choose<string>


Tr M<X1,...,Xn>(T1 x1, ..., Tm xm)


#### 第一個階段The first phase

• 如果 Ei 是匿名函式，則會從 Ei明確的參數型別推斷明確的參數型別推斷）設為 TiIf Ei is an anonymous function, an explicit parameter type inference (Explicit parameter type inferences) is made from Ei to Ti
• 否則，如果 Ei 的類型為 U，而 xi 是值參數，則會UTi進行下限推斷Otherwise, if Ei has a type U and xi is a value parameter then a lower-bound inference is made from U to Ti.
• 否則，如果 Ei 的類型為 U，而 xirefout 參數，那麼就會UTi進行完全推斷Otherwise, if Ei has a type U and xi is a ref or out parameter then an exact inference is made from U to Ti.
• 否則，就不會對這個引數進行推斷。Otherwise, no inference is made for this argument.

#### 第二個階段The second phase

• 所有未固定的類型變數Xi相依于（相依性）任何Xj 都已修正（修正）。All unfixed type variables Xi which do not depend on (Dependence) any Xj are fixed (Fixing).
• 如果不存在這類類型變數，則所有未固定的類型變數 Xi 皆為下列所有保留的固定If no such type variables exist, all unfixed type variables Xi are fixed for which all of the following hold:
• 至少有一個類型變數 Xj 相依于 XiThere is at least one type variable Xj that depends on Xi
• Xi 具有非空白的界限集合Xi has a non-empty set of bounds
• 如果沒有這類類型變數，而且仍然有未固定的類型變數，型別推斷就會失敗。If no such type variables exist and there are still unfixed type variables, type inference fails.
• 否則，如果沒有任何進一步的未固定類型變數存在，型別推斷就會成功。Otherwise, if no further unfixed type variables exist, type inference succeeds.
• 否則，對於具有對應參數類型的所有引數 Ei Ti其中輸出類型輸出類型）包含未固定的類型變數 Xj輸入類型輸入類型）不是，則會EiTi進行輸出類型推斷輸出類型推斷）。Otherwise, for all arguments Ei with corresponding parameter type Ti where the output types (Output types) contain unfixed type variables Xj but the input types (Input types) do not, an output type inference (Output type inferences) is made from Ei to Ti. 然後會重複第二個階段。Then the second phase is repeated.

#### 夜間Dependence

Xj取決Xi，如果 Xj直接相依于Xi，或 Xi直接相依于 XkXk取決於XjXj depends on Xi if Xj depends directly on Xi or if Xi depends directly on Xk and Xk depends on Xj. 因此「相依于」是可轉移的，但不是「直接相依于」的反的關閉。Thus "depends on" is the transitive but not reflexive closure of "depends directly on".

#### 輸出類型推斷Output type inferences

• 如果 E 是具有推斷傳回類型的匿名函式 U（推斷的傳回型別），而 T 是具有傳回型別 Tb的委派型別或運算式樹狀結構型別，則會UTb進行較低的系結推斷（較低系結）。If E is an anonymous function with inferred return type U (Inferred return type) and T is a delegate type or expression tree type with return type Tb, then a lower-bound inference (Lower-bound inferences) is made from U to Tb.
• 否則，如果 E 是方法群組，而 T 是具有參數類型 T1...Tk 和傳回類型 Tb的委派類型或運算式樹狀結構類型，而且 E 具有類型 T1...Tk 的多載解析會產生傳回類型 U的單一方法，則會UTb進行下限推斷Otherwise, if E is a method group and T is a delegate type or expression tree type with parameter types T1...Tk and return type Tb, and overload resolution of E with the types T1...Tk yields a single method with return type U, then a lower-bound inference is made from U to Tb.
• 否則，如果 E 是具有類型 U的運算式，則會UT進行較低系結的推斷。Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T.
• 否則，就不會進行推斷。Otherwise, no inferences are made.

#### 明確參數型別推斷Explicit parameter type inferences

• 如果 E 是明確類型的匿名函式，且參數類型為 U1...Uk，而且 T 是具有參數類型 V1...Vk 的委派類型或運算式樹狀結構類型，然後針對每個Ui 進行 完全推斷確切推斷Ui對應的 0。If E is an explicitly typed anonymous function with parameter types U1...Uk and T is a delegate type or expression tree type with parameter types V1...Vk then for each Ui an exact inference (Exact inferences) is made from Ui to the corresponding Vi.

#### 確切推斷Exact inferences

• 如果 V 為未固定Xi 之一，則 U 會加入至 Xi的確切界限集合。If V is one of the unfixed Xi then U is added to the set of exact bounds for Xi.

• 否則，會藉由檢查是否有下列情況來決定 V1...VkU1...UkOtherwise, sets V1...Vk and U1...Uk are determined by checking if any of the following cases apply:

• V 是陣列類型 V1[...] 而且 U 是相同次序的陣列類型 U1[...]V is an array type V1[...] and U is an array type U1[...] of the same rank
• V 是類型 V1? 而且 U 是類型 U1?V is the type V1? and U is the type U1?
• V 是結構化型別 C<V1...Vk>而且 U 是結構化型別 C<U1...Uk>V is a constructed type C<V1...Vk>and U is a constructed type C<U1...Uk>

如果套用上述任何一種情況，則會Ui對應的 Vi進行完全推斷If any of these cases apply then an exact inference is made from each Ui to the corresponding Vi.

• 否則不會進行推斷。Otherwise no inferences are made.

#### 下限推斷Lower-bound inferences

• 如果 V 為未固定Xi 之一，則 U 會加入至 Xi的下限集合。If V is one of the unfixed Xi then U is added to the set of lower bounds for Xi.

• 否則，如果 V 是類型 V1?而且 U 是類型 U1? 則會從 U1V1進行下限推斷。Otherwise, if V is the type V1?and U is the type U1? then a lower bound inference is made from U1 to V1.

• 否則，會藉由檢查是否有下列情況來決定 U1...UkV1...VkOtherwise, sets U1...Uk and V1...Vk are determined by checking if any of the following cases apply:

• V 是陣列類型 V1[...] 而且 U 是相同次序的陣列類型 U1[...] （或其有效基底類型為 U1[...]的類型參數）V is an array type V1[...] and U is an array type U1[...] (or a type parameter whose effective base type is U1[...]) of the same rank

• VIEnumerable<V1>ICollection<V1>IList<V1> 的其中一個，而 U 是一維陣列類型 U1[]（或其有效基底類型為 U1[]的類型參數）V is one of IEnumerable<V1>, ICollection<V1> or IList<V1> and U is a one-dimensional array type U1[](or a type parameter whose effective base type is U1[])

• V 是一種結構化的類別、結構、介面或委派類型 C<V1...Vk> 而且有唯一的類型 C<U1...Uk>U （或者，如果 U 是類型參數、其有效的基類或其有效介面集的任何成員）與、繼承自（直接或間接），或直接或間接的 C<U1...Uk>V is a constructed class, struct, interface or delegate type C<V1...Vk> and there is a unique type C<U1...Uk> such that U (or, if U is a type parameter, its effective base class or any member of its effective interface set) is identical to, inherits from (directly or indirectly), or implements (directly or indirectly) C<U1...Uk>.

（「唯一性」限制表示在案例介面中 C<T> {} class U: C<X>, C<Y> {}，從 U 推斷到 C<T> 時，不會進行推斷，因為 U1 可以 XY）。(The "uniqueness" restriction means that in the case interface C<T> {} class U: C<X>, C<Y> {}, then no inference is made when inferring from U to C<T> because U1 could be X or Y.)

如果套用上述任何一種情況，則會每個 Ui對應 Vi 進行推斷，如下所示：If any of these cases apply then an inference is made from each Ui to the corresponding Vi as follows:

• 如果 Ui 不知道是參考型別，則會進行完全推斷If Ui is not known to be a reference type then an exact inference is made
• 否則，如果 U 是陣列型別，則會進行較低界限的推斷Otherwise, if U is an array type then a lower-bound inference is made
• 否則，如果 V C<V1...Vk>，則推斷取決於 C的第 i 個類型參數：Otherwise, if V is C<V1...Vk> then inference depends on the i-th type parameter of C:
• 如果它是協變數，則會進行較低界限的推斷If it is covariant then a lower-bound inference is made.
• 如果它是逆變性，則會進行上限推斷If it is contravariant then an upper-bound inference is made.
• 如果它是不變的，則會進行完全推斷If it is invariant then an exact inference is made.
• 否則，就不會進行推斷。Otherwise, no inferences are made.

#### 上限推斷Upper-bound inferences

• 如果 V 為未固定Xi 之一，則 U 會加入至 Xi的上限集合。If V is one of the unfixed Xi then U is added to the set of upper bounds for Xi.

• 否則，會藉由檢查是否有下列情況來決定 V1...VkU1...UkOtherwise, sets V1...Vk and U1...Uk are determined by checking if any of the following cases apply:

• U 是陣列類型 U1[...] 而且 V 是相同次序的陣列類型 V1[...]U is an array type U1[...] and V is an array type V1[...] of the same rank

• UIEnumerable<Ue>ICollection<Ue>IList<Ue> 的其中一個，而 V 是一維陣列類型 Ve[]U is one of IEnumerable<Ue>, ICollection<Ue> or IList<Ue> and V is a one-dimensional array type Ve[]

• U 是類型 U1? 而且 V 是類型 V1?U is the type U1? and V is the type V1?

• U 是結構化的類別、結構、介面或委派類型 C<U1...Uk> 而且 V 是與相同的類別、結構、介面或委派類型、繼承自（直接或間接），或實作為唯一類型的（直接或間接） C<V1...Vk>U is constructed class, struct, interface or delegate type C<U1...Uk> and V is a class, struct, interface or delegate type which is identical to, inherits from (directly or indirectly), or implements (directly or indirectly) a unique type C<V1...Vk>

（「唯一性」限制表示如果我們有 interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}，則從 C<U1> 推斷到 V<Q>時，不會進行推斷。(The "uniqueness" restriction means that if we have interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}, then no inference is made when inferring from C<U1> to V<Q>. 推斷不會從 U1 進行，X<Q>Y<Q>）。Inferences are not made from U1 to either X<Q> or Y<Q>.)

如果套用上述任何一種情況，則會每個 Ui對應 Vi 進行推斷，如下所示：If any of these cases apply then an inference is made from each Ui to the corresponding Vi as follows:

• 如果 Ui 不知道是參考型別，則會進行完全推斷If Ui is not known to be a reference type then an exact inference is made
• 否則，如果 V 是陣列類型，則會進行上限推斷Otherwise, if V is an array type then an upper-bound inference is made
• 否則，如果 U C<U1...Uk>，則推斷取決於 C的第 i 個類型參數：Otherwise, if U is C<U1...Uk> then inference depends on the i-th type parameter of C:
• 如果它是協變數，則會進行上限推斷If it is covariant then an upper-bound inference is made.
• 如果是反變數，則會進行較低界限的推斷If it is contravariant then a lower-bound inference is made.
• 如果它是不變的，則會進行完全推斷If it is invariant then an exact inference is made.
• 否則，就不會進行推斷。Otherwise, no inferences are made.

#### 修正Fixing

• 候選類型的集合 Uj 一開始就是 Xi界限集合中的所有類型集合。The set of candidate types Uj starts out as the set of all types in the set of bounds for Xi.
• 接著，我們會檢查每個 Xi 的系結：對於 Xi 所有與 U 不完全相同的 U 之每個完全系結的 Uj，會從候選集合中移除。We then examine each bound for Xi in turn: For each exact bound U of Xi all types Uj which are not identical to U are removed from the candidate set. 對於 Xi 的每個下限 U，會從候選集合中移除是從 U 隱含轉換的所有類型 UjFor each lower bound U of Xi all types Uj to which there is not an implicit conversion from U are removed from the candidate set. 針對 Xi 的每個上限 U會從候選集合中移除隱含轉換成 U 的所有類型 UjFor each upper bound U of Xi all types Uj from which there is not an implicit conversion to U are removed from the candidate set.
• 如果剩餘的候選類型 Uj 有一個唯一的類型 V，其中隱含轉換至所有其他候選類型，則 Xi 會固定到 VIf among the remaining candidate types Uj there is a unique type V from which there is an implicit conversion to all the other candidate types, then Xi is fixed to V.
• 否則，型別推斷會失敗。Otherwise, type inference fails.

#### 推斷的傳回型別Inferred return type

• 如果 F 的主體是具有型別的運算式，則 F 的推斷結果型別就是該運算式的型別。If the body of F is an expression that has a type, then the inferred result type of F is the type of that expression.
• 如果 F 的主體是區塊，而且區塊的 return 語句中的運算式集合具有最佳的一般類型 T尋找一組運算式的最佳一般類型），則會 T所推斷的結果 F 類型。If the body of F is a block and the set of expressions in the block's return statements has a best common type T (Finding the best common type of a set of expressions), then the inferred result type of F is T.
• 否則，將無法推斷 F的結果類型。Otherwise, a result type cannot be inferred for F.

• 如果 F 是非同步，而且 F 的主體是分類為「無」（運算式分類）的運算式，或是不含任何傳回語句的語句區塊，則推斷的傳回型別會 System.Threading.Tasks.TaskIf F is async and the body of F is either an expression classified as nothing (Expression classifications), or a statement block where no return statements have expressions, the inferred return type is System.Threading.Tasks.Task
• 如果 F 是非同步，而且具有 T的推斷結果類型，則會 System.Threading.Tasks.Task<T>推斷的傳回類型。If F is async and has an inferred result type T, the inferred return type is System.Threading.Tasks.Task<T>.
• 如果 F 是非非同步，而且具有 T的推斷結果型別，則會 T推斷的傳回型別。If F is non-async and has an inferred result type T, the inferred return type is T.
• 否則，將無法推斷 F的傳回型別。Otherwise a return type cannot be inferred for F.

namespace System.Linq
{
public static class Enumerable
{
public static IEnumerable<TResult> Select<TSource,TResult>(
this IEnumerable<TSource> source,
Func<TSource,TResult> selector)
{
foreach (TSource element in source) yield return selector(element);
}
}
}


List<Customer> customers = GetCustomerList();
IEnumerable<string> names = customers.Select(c => c.Name);


Select 的擴充方法叫用（擴充方法調用）是藉由將調用重寫為靜態方法調用來處理：The extension method invocation (Extension method invocations) of Select is processed by rewriting the invocation to a static method invocation:

IEnumerable<string> names = Enumerable.Select(customers, c => c.Name);


Sequence.Select<Customer,string>(customers, (Customer c) => c.Name)


static Z F<X,Y,Z>(X value, Func<X,Y> f1, Func<Y,Z> f2) {
return f2(f1(value));
}


double seconds = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds);


#### 方法群組轉換的型別推斷Type inference for conversion of method groups

Tr M<X1...Xn>(T1 x1 ... Tm xm)


M<S1...Sn>


D變得相容（委派宣告）。becomes compatible (Delegate declarations) with D.

#### 尋找一組運算式的最佳一般類型Finding the best common type of a set of expressions

Tr M<X>(X x1 ... X xm)


with Ei 做為引數。with the Ei as arguments.

• 假設有一組適用的候選函式成員，就會找到該集合中的最佳函式成員。Given the set of applicable candidate function members, the best function member in that set is located. 如果集合僅包含一個函式成員，則該函式成員就是最佳的函式成員。If the set contains only one function member, then that function member is the best function member. 否則，最佳的函式成員就是一個優於指定引數清單的所有其他函式成員的函式成員，前提是每個函式成員都會使用更好的函式成員中的規則來與其他所有函式成員進行比較。Otherwise, the best function member is the one function member that is better than all other function members with respect to the given argument list, provided that each function member is compared to all other function members using the rules in Better function member. 如果沒有一個比所有其他函式成員更好的函式成員，則函式成員調用是不明確的，而且會發生系結時錯誤。If there is not exactly one function member that is better than all other function members, then the function member invocation is ambiguous and a binding-time error occurs.

#### 適用的函式成員Applicable function member

• A 中的每個引數都會對應至函式成員宣告中的參數（如對應的參數中所述），而且任何沒有引數對應的參數都是選擇性參數。Each argument in A corresponds to a parameter in the function member declaration as described in Corresponding parameters, and any parameter to which no argument corresponds is an optional parameter.
• 針對 A中的每個引數，引數的參數傳遞模式（亦即，value、refout）等同于對應參數的參數傳遞模式，以及For each argument in A, the parameter passing mode of the argument (i.e., value, ref, or out) is identical to the parameter passing mode of the corresponding parameter, and
• 針對值參數或參數陣列，隱含轉換（隱含轉換）會從引數到對應參數的類型，或for a value parameter or a parameter array, an implicit conversion (Implicit conversions) exists from the argument to the type of the corresponding parameter, or
• 若為 refout 參數，引數的類型與對應參數的類型相同。for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter. 畢竟，refout 參數是所傳遞之引數的別名。After all, a ref or out parameter is an alias for the argument passed.

• 藉由將函式成員宣告中的參數陣列取代為參數陣列之元素類型的零個或多個值參數，讓引數清單中的引數數目 A 符合參數的總數目，來建立展開的表單。The expanded form is constructed by replacing the parameter array in the function member declaration with zero or more value parameters of the element type of the parameter array such that the number of arguments in the argument list A matches the total number of parameters. 如果 A 的引數數目比函式成員宣告中的固定參數數少，則無法構造函式成員的展開形式，因此不適用。If A has fewer arguments than the number of fixed parameters in the function member declaration, the expanded form of the function member cannot be constructed and is thus not applicable.
• 否則，如果對中的每個引數 A，引數的參數傳遞模式等同于對應參數的參數傳遞模式，則適用展開的表單。Otherwise, the expanded form is applicable if for each argument in A the parameter passing mode of the argument is identical to the parameter passing mode of the corresponding parameter, and
• 若為 fixed 值參數或擴充所建立的值參數，隱含轉換（隱含轉換）會從引數的類型存在對應的參數類型中，或for a fixed value parameter or a value parameter created by the expansion, an implicit conversion (Implicit conversions) exists from the type of the argument to the type of the corresponding parameter, or
• 若為 refout 參數，引數的類型與對應參數的類型相同。for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter.

#### 更好的函式成員Better function member

• 如果函式成員僅適用于展開的形式，則會使用展開的表單。The expanded form is used if the function member was applicable only in the expanded form.
• 不含對應引數的選擇性參數會從參數清單中移除Optional parameters with no corresponding arguments are removed from the parameter list
• 這些參數會重新排序，使其出現在引數清單中與對應引數相同的位置。The parameters are reordered so that they occur at the same position as the corresponding argument in the argument list.

• 針對每個引數，從 ExQx 的隱含轉換不會優於從 ExPx的隱含轉換。for each argument, the implicit conversion from Ex to Qx is not better than the implicit conversion from Ex to Px, and
• 針對至少一個引數，從 ExPx 的轉換比從 Ex 轉換為 Qx的效果更好。for at least one argument, the conversion from Ex to Px is better than the conversion from Ex to Qx.

• 如果 Mp 是非泛型方法，而 Mq 是泛型方法，則 MpMq好。If Mp is a non-generic method and Mq is a generic method, then Mp is better than Mq.
• 否則，如果 Mp 適用于其標準格式，且 Mq 具有 params 陣列，而且只適用于其展開的格式，則 Mp 會優於 MqOtherwise, if Mp is applicable in its normal form and Mq has a params array and is applicable only in its expanded form, then Mp is better than Mq.
• 否則，如果 Mp 的宣告參數數超過 Mq，則 MpMq好。Otherwise, if Mp has more declared parameters than Mq, then Mp is better than Mq. 如果這兩個方法都有 params 陣列，而且只適用于其展開的形式，就會發生這種情況。This can occur if both methods have params arrays and are applicable only in their expanded forms.
• 否則，如果 Mp 的所有參數都有對應的引數，而預設引數必須在 Mq 中取代為至少一個選擇性參數，則 MpMq更好。Otherwise if all parameters of Mp have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in Mq then Mp is better than Mq.
• 否則，如果 Mp 具有比 Mq更多的特定參數類型，則 Mp 會優於 MqOtherwise, if Mp has more specific parameter types than Mq, then Mp is better than Mq. {R1, R2, ..., Rn}{S1, S2, ..., Sn} 代表 MpMq的未具現化和未展開的參數類型。Let {R1, R2, ..., Rn} and {S1, S2, ..., Sn} represent the uninstantiated and unexpanded parameter types of Mp and Mq. Mp的參數類型比 Mq更具體的是，如果每個參數的 Rx 不是特定于 Sx，而且至少有一個參數，則 RxSx更明確：Mp's parameter types are more specific than Mq's if, for each parameter, Rx is not less specific than Sx, and, for at least one parameter, Rx is more specific than Sx:
• 型別參數比非型別參數較不明確。A type parameter is less specific than a non-type parameter.
• 如果至少有一個型別引數較明確，而且沒有任何型別引數比另一個中的對應型別引數更明確，則結構化型別會以遞迴方式比另一個結構化型別更明確（具有相同的型別引數數目）。Recursively, a constructed type is more specific than another constructed type (with the same number of type arguments) if at least one type argument is more specific and no type argument is less specific than the corresponding type argument in the other.
• 如果第一個陣列類型的專案類型比第二個數組類型的專案類型更明確，則陣列型別會比另一個陣列型別更明確（具有相同的維度數目）。An array type is more specific than another array type (with the same number of dimensions) if the element type of the first is more specific than the element type of the second.
• 否則，如果一個成員是一個非提升運算子，另一個則是提升運算子，則不會提升。Otherwise if one member is a non-lifted operator and the other is a lifted operator, the non-lifted one is better.
• 否則，函數成員都不會更好。Otherwise, neither function member is better.

#### 完全相符的運算式Exactly matching Expression

• E 具有 S類型，而且從 S 到的身分識別轉換已存在 TE has a type S, and an identity conversion exists from S to T
• E 是匿名函式，T 是委派類型 D 或運算式樹狀架構類型 Expression<D> 和下列其中一項保留：E is an anonymous function, T is either a delegate type D or an expression tree type Expression<D> and one of the following holds:
• D （推斷的傳回別）的參數清單內容中，E 的推斷傳回型別 X 存在，而且從 X 到傳回型別的識別轉換存在 DAn inferred return type X exists for E in the context of the parameter list of D (Inferred return type), and an identity conversion exists from X to the return type of D
• E 是非非同步，而且 D 有傳回型別 YE 是非同步，而且 D 有傳回型別 Task<Y>，而下列其中一項保留：Either E is non-async and D has a return type Y or E is async and D has a return type Task<Y>, and one of the following holds:
• E 的主體是完全符合 Y 的運算式The body of E is an expression that exactly matches Y
• E 的主體是語句區塊，其中每個傳回語句都會傳回完全符合的運算式 YThe body of E is a statement block where every return statement returns an expression that exactly matches Y

#### 較佳的轉換目標Better conversion target

• T1T2 的隱含轉換已存在An implicit conversion from T1 to T2 exists
• T1 是委派類型 D1 或運算式樹狀結構類型 Expression<D1>T2 是委派類型 D2 或運算式樹狀結構類型 Expression<D2>D1 有傳回類型 S1 和下列其中一項保留：T1 is either a delegate type D1 or an expression tree type Expression<D1>, T2 is either a delegate type D2 or an expression tree type Expression<D2>, D1 has a return type S1 and one of the following holds:
• D2 傳回 voidD2 is void returning
• D2 具有 S2的傳回類型，而 S1 是比 S2 更佳的轉換目標D2 has a return type S2, and S1 is a better conversion target than S2
• T1Task<S1>T2Task<S2>，而 S1 是比 S2 更佳的轉換目標T1 is Task<S1>, T2 is Task<S2>, and S1 is a better conversion target than S2
• T1S1S1?，其中 S1 是帶正負號的整數類資料類型，而 T2 S2S2?，其中 S2 是不帶正負號的整數類資料類型。T1 is S1 or S1? where S1 is a signed integral type, and T2 is S2 or S2? where S2 is an unsigned integral type. 尤其是：Specifically:
• S1sbyteS2byteushortuintulongS1 is sbyte and S2 is byte, ushort, uint, or ulong
• S1shortS2ushortuintulongS1 is short and S2 is ushort, uint, or ulong
• S1intS2uint，或 ulongS1 is int and S2 is uint, or ulong
• S1longS2ulongS1 is long and S2 is ulong

interface I1<T> {...}

interface I2<T> {...}

class G1<U>
{
int F1(U u);                  // Overload resolution for G<int>.F1
int F1(int i);                // will pick non-generic

void F2(I1<U> a);             // Valid overload
void F2(I2<U> a);
}

class G2<U,V>
{
void F3(U u, V v);            // Valid, but overload resolution for
void F3(V v, U u);            // G2<int,int>.F3 will fail

void F4(U u, I1<V> v);        // Valid, but overload resolution for
void F4(I1<V> v, U u);        // G2<I1<int>,int>.F4 will fail

void F5(U u1, I1<V> v2);      // Valid overload
void F5(V v1, U u2);

void F6(ref U u);             // valid overload
void F6(out V v);
}


### 動態多載解析的編譯階段檢查Compile-time checking of dynamic overload resolution

• 使用動態引數的靜態方法呼叫Static method calls with dynamic arguments
• 接收者不是動態運算式的實例方法呼叫Instance method calls where the receiver is not a dynamic expression
• 接收者不是動態運算式的索引子呼叫Indexer calls where the receiver is not a dynamic expression
• 使用動態引數的函式呼叫Constructor calls with dynamic arguments

• 部分型別推斷：不直接或間接相依于型別 dynamic 之引數的任何型別引數，都會使用型別推斷的規則來推斷。Partial type inference: Any type argument that does not depend directly or indirectly on an argument of type dynamic is inferred using the rules of Type inference. 其餘的類型引數不明。The remaining type arguments are unknown.
• 部分適用性檢查：適用性是根據適用的函式成員進行檢查，但忽略其類型不明的參數。Partial applicability check: Applicability is checked according to Applicable function member, but ignoring parameters whose types are unknown.
• 如果沒有候選項通過這項測試，就會發生編譯時期錯誤。If no candidate passes this test, a compile-time error occurs.

### 函數成員調用Function member invocation

• 靜態函式成員。Static function members. 這些是實例的構造函式、靜態方法、靜態屬性存取子和使用者定義的運算子。These are instance constructors, static methods, static property accessors, and user-defined operators. 靜態函式成員一律為非虛擬。Static function members are always non-virtual.
• 實例函式成員。Instance function members. 這些是實例方法、實例屬性存取子和索引子存取子。These are instance methods, instance property accessors, and indexer accessors. 實例函式成員為非虛擬或虛擬，而且一律會在特定實例上叫用。Instance function members are either non-virtual or virtual, and are always invoked on a particular instance. 實例是由實例運算式所計算，並可在函式成員中以 this此存取權）的形式存取。The instance is computed by an instance expression, and it becomes accessible within the function member as this (This access).

• 如果 M 是靜態函式成員：If M is a static function member:

• 引數清單會依照引數清單中的說明進行評估。The argument list is evaluated as described in Argument lists.
• 叫用 MM is invoked.
• 如果 M 是在value_type中宣告的實例函式成員：If M is an instance function member declared in a value_type:

• 評估 EE is evaluated. 如果此評估導致例外狀況，則不會執行任何進一步的步驟。If this evaluation causes an exception, then no further steps are executed.
• 如果 E 未分類為變數，則會建立 E類型的暫存區域變數，並將 E 的值指派給該變數。If E is not classified as a variable, then a temporary local variable of E's type is created and the value of E is assigned to that variable. E 接著會重新分類為該暫存區域變數的參考。E is then reclassified as a reference to that temporary local variable. 暫存變數可在 M內以 this 的方式來存取，但不能以任何其他方法來存取。The temporary variable is accessible as this within M, but not in any other way. 因此，只有當 E 是真正的變數時，呼叫端才能夠觀察 Mthis進行的變更。Thus, only when E is a true variable is it possible for the caller to observe the changes that M makes to this.
• 引數清單會依照引數清單中的說明進行評估。The argument list is evaluated as described in Argument lists.
• 叫用 MM is invoked. E 所參考的變數會成為 this所參考的變數。The variable referenced by E becomes the variable referenced by this.
• 如果 M 是在reference_type中宣告的實例函式成員：If M is an instance function member declared in a reference_type:

• 評估 EE is evaluated. 如果此評估導致例外狀況，則不會執行任何進一步的步驟。If this evaluation causes an exception, then no further steps are executed.
• 引數清單會依照引數清單中的說明進行評估。The argument list is evaluated as described in Argument lists.
• 如果 E 的類型是value_type，則會執行「裝箱轉換」（「裝箱轉換」）來將 E 轉換為類型 object，而 E 會被視為在下列步驟中 object 的類型。If the type of E is a value_type, a boxing conversion (Boxing conversions) is performed to convert E to type object, and E is considered to be of type object in the following steps. 在此情況下，M 只能是 System.Object的成員。In this case, M could only be a member of System.Object.
• 已檢查 E 的值為有效。The value of E is checked to be valid. 如果 E 的值為 null，則會擲回 System.NullReferenceException，而且不會執行任何進一步的步驟。If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.
• 會決定要叫用的函式成員實作為：The function member implementation to invoke is determined:
• 如果 E 的系結時間類型是介面，則叫用的函式成員就是由 E所參考之實例的執行時間類型所提供的 M 的執行。If the binding-time type of E is an interface, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. 這個函式成員的決定方式是套用介面對應規則（介面對應），以判斷 E所參考之實例的執行時間類型所提供的 M 的執行。This function member is determined by applying the interface mapping rules (Interface mapping) to determine the implementation of M provided by the run-time type of the instance referenced by E.
• 否則，如果 M 是虛擬函式成員，則叫用的函式成員就是由 E所參考之實例的執行時間類型所提供的 M 的執行。Otherwise, if M is a virtual function member, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. 這個函式成員的決定方式，是套用用來判斷 M 之最衍生的實（虛擬方法）的規則（相對於 E所參考之實例的執行時間型別）。This function member is determined by applying the rules for determining the most derived implementation (Virtual methods) of M with respect to the run-time type of the instance referenced by E.
• 否則，M 為非虛擬函式成員，而要叫用的函式成員則 M 本身。Otherwise, M is a non-virtual function member, and the function member to invoke is M itself.
• 叫用上述步驟中判斷的函式成員實作為。The function member implementation determined in the step above is invoked. E 所參考的物件會成為 this所參考的物件。The object referenced by E becomes the object referenced by this.

#### 在已裝箱實例上的調用Invocations on boxed instances

• 當函式成員是繼承自類型 object 之方法的 override，而且會透過類型 object的實例運算式來叫用。When the function member is an override of a method inherited from type object and is invoked through an instance expression of type object.
• 當函式成員是介面函數成員的執行，而且是透過interface_type的實例運算式來叫用時。When the function member is an implementation of an interface function member and is invoked through an instance expression of an interface_type.
• 當函式成員透過委派叫用時。When the function member is invoked through a delegate.

## 主要運算式Primary expressions

primary_expression
: primary_no_array_creation_expression
| array_creation_expression
;

primary_no_array_creation_expression
: literal
| interpolated_string_expression
| simple_name
| parenthesized_expression
| member_access
| invocation_expression
| element_access
| this_access
| base_access
| post_increment_expression
| post_decrement_expression
| object_creation_expression
| delegate_creation_expression
| anonymous_object_creation_expression
| typeof_expression
| checked_expression
| unchecked_expression
| default_value_expression
| nameof_expression
| anonymous_method_expression
| primary_no_array_creation_expression_unsafe
;


object o = new int[3][1];


object o = (new int[3])[1];


### 插入字串Interpolated strings

Interpolated_string_expression包含 $ 符號，後面接著一般或逐字字串常值，其中的洞會以 {}分隔，並括住運算式和格式設定規格。An interpolated_string_expression consists of a $ sign followed by a regular or verbatim string literal, wherein holes, delimited by { and }, enclose expressions and formatting specifications. 內插字串運算式是指已細分為個別 token 的interpolated_string_literal結果，如插入字串常值中所述。An interpolated string expression is the result of an interpolated_string_literal that has been broken up into individual tokens, as described in Interpolated string literals.

interpolated_string_expression
: '$' interpolated_regular_string | '$' interpolated_verbatim_string
;

interpolated_regular_string
: interpolated_regular_string_whole
| interpolated_regular_string_start interpolated_regular_string_body interpolated_regular_string_end
;

interpolated_regular_string_body
: interpolation (interpolated_regular_string_mid interpolation)*
;

interpolation
: expression
| expression ',' constant_expression
;

interpolated_verbatim_string
: interpolated_verbatim_string_whole
| interpolated_verbatim_string_start interpolated_verbatim_string_body interpolated_verbatim_string_end
;

interpolated_verbatim_string_body
: interpolation (interpolated_verbatim_string_mid interpolation)+
;


Interpolated_string_expression會分類為值。An interpolated_string_expression is classified as a value. 如果它會立即轉換成 System.IFormattable 或具有隱含插入字串轉換的 System.FormattableString隱含插入字串轉換），則字串插值運算式就會有該類型。If it is immediately converted to System.IFormattable or System.FormattableString with an implicit interpolated string conversion (Implicit interpolated string conversions), the interpolated string expression has that type. 否則，它的類型 stringOtherwise, it has the type string.

• 如果interpolated_regular_string_wholeinterpolated_verbatim_string_whole遵循 $ 正負號，則格式字串常值就是該 token。If an interpolated_regular_string_whole or an interpolated_verbatim_string_whole follows the $ sign, then the format string literal is that token.
• 否則，格式字串常值包含：Otherwise, the format string literal consists of:
• 首先interpolated_regular_string_startinterpolated_verbatim_string_startFirst the interpolated_regular_string_start or interpolated_verbatim_string_start
• 然後，將每個數位從 0 IN-1Then for each number I from 0 to N-1:
• I 的十進位標記法The decimal representation of I
• 然後，如果對應的插補具有constant_expression, （逗號），後面接著其值的十進位標記法constant_expressionThen, if the corresponding interpolation has a constant_expression, a , (comma) followed by the decimal representation of the value of the constant_expression
• 接著， interpolated_regular_string_midinterpolated_regular_string_endinterpolated_verbatim_string_midinterpolated_verbatim_string_end緊接在對應的插補後面。Then the interpolated_regular_string_mid, interpolated_regular_string_end, interpolated_verbatim_string_mid or interpolated_verbatim_string_end immediately following the corresponding interpolation.

TODO：範例。TODO: examples.

### 簡單名稱Simple names

Simple_name包含識別碼，並選擇性地加上類型引數清單：A simple_name consists of an identifier, optionally followed by a type argument list:

simple_name
: identifier type_argument_list?
;


Simple_name的格式 I 或形式 I<A1,...,Ak>，其中 I 是單一識別碼，而 <A1,...,Ak> 是選擇性的type_argument_listA simple_name is either of the form I or of the form I<A1,...,Ak>, where I is a single identifier and <A1,...,Ak> is an optional type_argument_list. 若未指定type_argument_list ，請考慮將 K 為零。When no type_argument_list is specified, consider K to be zero. Simple_name的評估和分類方式如下：The simple_name is evaluated and classified as follows:

• 如果 K 為零，且simple_name出現在區塊內，而且如果區塊的（或封閉區塊的）本機變數宣告空間（宣告）包含本機變數、參數或具有名稱 I的常數，則simple_name會參考該區域變數、參數或常數，並將其分類為變數或值。If K is zero and the simple_name appears within a block and if the block's (or an enclosing block's) local variable declaration space (Declarations) contains a local variable, parameter or constant with name I, then the simple_name refers to that local variable, parameter or constant and is classified as a variable or value.

• 如果 K 為零，且simple_name出現在泛型方法宣告的主體內，而且如果該宣告包含名稱為 I的型別參數，則simple_name會參考該型別參數。If K is zero and the simple_name appears within the body of a generic method declaration and if that declaration includes a type parameter with name I, then the simple_name refers to that type parameter.

• 否則，針對每個實例類型 T實例類型），從立即封入類型宣告的實例類型開始，並繼續進行每個封入類別或結構宣告的實例類型（如果有的話）：Otherwise, for each instance type T (The instance type), starting with the instance type of the immediately enclosing type declaration and continuing with the instance type of each enclosing class or struct declaration (if any):

• 如果 K 為零，且 T 的宣告包含名稱為 I的類型參數，則simple_name會參考該類型參數。If K is zero and the declaration of T includes a type parameter with name I, then the simple_name refers to that type parameter.
• 否則，如果 TI 的成員查閱（成員查閱）與 K 型別引數，則會產生符合的結果：Otherwise, if a member lookup (Member lookup) of I in T with K type arguments produces a match:
• 如果 T 是立即封入類別或結構型別的實例型別，而且查閱識別一或多個方法，則結果會是具有 this之相關聯實例運算式的方法群組。If T is the instance type of the immediately enclosing class or struct type and the lookup identifies one or more methods, the result is a method group with an associated instance expression of this. 如果指定了類型引數清單，則會使用它來呼叫泛型方法（方法調用）。If a type argument list was specified, it is used in calling a generic method (Method invocations).
• 否則，如果 T 是立即封入類別或結構型別的實例型別，而且查閱識別出實例成員，而且如果參考發生在實例的函式、實例方法或實例存取子的主體內，則結果會與表單 this.I的成員存取權（成員存取）相同。Otherwise, if T is the instance type of the immediately enclosing class or struct type, if the lookup identifies an instance member, and if the reference occurs within the body of an instance constructor, an instance method, or an instance accessor, the result is the same as a member access (Member access) of the form this.I. 只有當 K 為零時，才會發生這種情況。This can only happen when K is zero.
• 否則，結果會與表單 T.IT.I<A1,...,Ak>的成員存取權（成員存取權）相同。Otherwise, the result is the same as a member access (Member access) of the form T.I or T.I<A1,...,Ak>. 在此情況下，這是simple_name參考實例成員的系結時錯誤。In this case, it is a binding-time error for the simple_name to refer to an instance member.
• 否則，針對每個命名空間 N，從發生simple_name的命名空間開始，繼續進行每個封入命名空間（如果有的話），並以全域命名空間結束，直到實體找到之後，才會評估下列步驟：Otherwise, for each namespace N, starting with the namespace in which the simple_name occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located:

• 如果 K 為零，且 I 是 N中的命名空間名稱，則：If K is zero and I is the name of a namespace in N, then:
• 如果simple_name發生所在的位置是以 N 的命名空間宣告括住，且命名空間宣告包含extern_alias_directiveusing_alias_directive ，將名稱 I 與命名空間或類型產生關聯，則simple_name會不明確，且會發生編譯時期錯誤。If the location where the simple_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the simple_name is ambiguous and a compile-time error occurs.
• 否則， simple_name會參考 N中名為 I 的命名空間。Otherwise, the simple_name refers to the namespace named I in N.
• 否則，如果 N 包含名稱 I 的可存取型別，且 K 型別參數，則：Otherwise, if N contains an accessible type having name I and K type parameters, then:
• 如果 K 為零，且發生simple_name的位置是以 N 的命名空間宣告括住，且命名空間宣告包含extern_alias_directiveusing_alias_directive關聯名稱 I 與命名空間或類型，則simple_name不明確，且會發生編譯時期錯誤。If K is zero and the location where the simple_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the simple_name is ambiguous and a compile-time error occurs.
• 否則， namespace_or_type_name會參考以指定的型別引數所構成的型別。Otherwise, the namespace_or_type_name refers to the type constructed with the given type arguments.
• 否則，如果發生simple_name的位置是以 N的命名空間宣告括住：Otherwise, if the location where the simple_name occurs is enclosed by a namespace declaration for N:
• 如果 K 為零，且命名空間宣告包含extern_alias_directiveusing_alias_directive將名稱 I 與匯入的命名空間或類型產生關聯，則simple_name會參考該命名空間或類型。If K is zero and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with an imported namespace or type, then the simple_name refers to that namespace or type.
• 否則，如果由using_namespace_directives 與using_static_directive的命名空間宣告所匯入的命名空間和類型宣告，只包含一個可存取的類型或非延伸的靜態成員（名稱 I，而 K 類型參數），則simple_name會參考以給定類型引數所建立的類型或成員。Otherwise, if the namespaces and type declarations imported by the using_namespace_directives and using_static_directives of the namespace declaration contain exactly one accessible type or non-extension static member having name I and K type parameters, then the simple_name refers to that type or member constructed with the given type arguments.
• 否則，如果命名空間宣告的using_namespace_directives 所匯入的命名空間和類型包含一個以上的可存取類型或非擴充方法的靜態成員名稱 IK 類型參數，則simple_name會是不明確的，而且會發生錯誤。Otherwise, if the namespaces and types imported by the using_namespace_directives of the namespace declaration contain more than one accessible type or non-extension-method static member having name I and K type parameters, then the simple_name is ambiguous and an error occurs.

請注意，這整個步驟與處理namespace_or_type_name命名空間和型別名稱）中的對應步驟完全平行。Note that this entire step is exactly parallel to the corresponding step in the processing of a namespace_or_type_name (Namespace and type names).

• 否則，不會定義simple_name ，而且會發生編譯時期錯誤。Otherwise, the simple_name is undefined and a compile-time error occurs.

### 以括弧括住的運算式Parenthesized expressions

Parenthesized_expression包含以括弧括住的運算式A parenthesized_expression consists of an expression enclosed in parentheses.

parenthesized_expression
: '(' expression ')'
;


### 成員存取Member access

Member_accessprimary_expressionpredefined_typequalified_alias_member組成，後面接著 "." 權杖，後面接著一個識別碼，可選擇性地加上type_argument_listA member_access consists of a primary_expression, a predefined_type, or a qualified_alias_member, followed by a "." token, followed by an identifier, optionally followed by a type_argument_list.

member_access
: primary_expression '.' identifier type_argument_list?
| predefined_type '.' identifier type_argument_list?
| qualified_alias_member '.' identifier
;

predefined_type
: 'bool'   | 'byte'  | 'char'  | 'decimal' | 'double' | 'float' | 'int' | 'long'
| 'object' | 'sbyte' | 'short' | 'string'  | 'uint'   | 'ulong' | 'ushort'
;


Qualified_alias_member的生產環境是在命名空間別名限定詞中定義。The qualified_alias_member production is defined in Namespace alias qualifiers.

Member_access的格式為 E.I 或表單 E.I<A1, ..., Ak>，其中 E 是主要運算式，I 是單一識別碼，而 <A1, ..., Ak> 是選擇性的type_argument_listA member_access is either of the form E.I or of the form E.I<A1, ..., Ak>, where E is a primary-expression, I is a single identifier and <A1, ..., Ak> is an optional type_argument_list. 若未指定type_argument_list ，請考慮將 K 為零。When no type_argument_list is specified, consider K to be zero.

Primary_expression類型為 dynamicmember_access會動態繫結（動態系結）。A member_access with a primary_expression of type dynamic is dynamically bound (Dynamic binding). 在此情況下，編譯器會將成員存取分類為 dynamic類型的屬性存取。In this case the compiler classifies the member access as a property access of type dynamic. 下列規則會在執行時間套用member_access的意義，並使用執行時間類型，而不是primary_expression的編譯時間類型。The rules below to determine the meaning of the member_access are then applied at run-time, using the run-time type instead of the compile-time type of the primary_expression. 如果此執行時間分類會導致方法群組，則成員存取必須是invocation_expressionprimary_expressionIf this run-time classification leads to a method group, then the member access must be the primary_expression of an invocation_expression.

Member_access的評估和分類方式如下：The member_access is evaluated and classified as follows:

• 如果 K 為零，且 E 是命名空間，而 E 包含名稱為 I的嵌套命名空間，則結果會是該命名空間。If K is zero and E is a namespace and E contains a nested namespace with name I, then the result is that namespace.
• 否則，如果 E 是命名空間，而 E 包含名稱 I 的可存取型別，而且 K 型別參數，則結果會是以給定型別引數所構成的型別。Otherwise, if E is a namespace and E contains an accessible type having name I and K type parameters, then the result is that type constructed with the given type arguments.
• 如果 Epredefined_type或分類為類型的primary_expression ，如果 E 不是型別參數，而且 IE 的成員查閱（成員查閱K型別參數會產生相符項，則會評估  並分類如下：If E is a predefined_type or a primary_expression classified as a type, if E is not a type parameter, and if a member lookup (Member lookup) of I in E with K type parameters produces a match, then E.I is evaluated and classified as follows:
• 如果 I 識別型別，則結果會是以給定型別引數所構成的型別。If I identifies a type, then the result is that type constructed with the given type arguments.
• 如果 I 識別一個或多個方法，則結果會是沒有相關聯實例運算式的方法群組。If I identifies one or more methods, then the result is a method group with no associated instance expression. 如果指定了類型引數清單，則會使用它來呼叫泛型方法（方法調用）。If a type argument list was specified, it is used in calling a generic method (Method invocations).
• 如果 I 識別 static 屬性，則結果會是沒有相關聯實例運算式的屬性存取。If I identifies a static property, then the result is a property access with no associated instance expression.
• 如果 I 識別 static 欄位：If I identifies a static field:
• 如果欄位是 readonly 且參考發生在宣告欄位之類別或結構的靜態函式外，則結果會是值，也就是 E中靜態欄位 I 的值。If the field is readonly and the reference occurs outside the static constructor of the class or struct in which the field is declared, then the result is a value, namely the value of the static field I in E.
• 否則，結果會是變數，也就是 E中 I 的靜態欄位。Otherwise, the result is a variable, namely the static field I in E.
• 如果 I 識別 static 事件：If I identifies a static event:
• 如果參考發生在宣告事件的類別或結構中，而事件是在沒有event_accessor_declarations事件）的情況下宣告，則 E.I 的處理方式完全如同 I 是靜態欄位一樣。If the reference occurs within the class or struct in which the event is declared, and the event was declared without event_accessor_declarations (Events), then E.I is processed exactly as if I were a static field.
• 否則，結果會是沒有相關聯實例運算式的事件存取。Otherwise, the result is an event access with no associated instance expression.
• 如果 I 識別常數，則結果會是值，也就是該常數的值。If I identifies a constant, then the result is a value, namely the value of that constant.
• 如果 I 識別列舉成員，則結果會是值，也就是該列舉成員的值。If I identifies an enumeration member, then the result is a value, namely the value of that enumeration member.
• 否則，E.I 是不正確成員參考，而且發生編譯時期錯誤。Otherwise, E.I is an invalid member reference, and a compile-time error occurs.
• 如果 E 是屬性存取、索引子存取、變數或值、 T的類型，以及 K 類型引數的 T 中的成員查閱（成員查閱I）會產生相符項，則會評估 E.I 並將其分類如下：If E is a property access, indexer access, variable, or value, the type of which is T, and a member lookup (Member lookup) of I in T with K type arguments produces a match, then E.I is evaluated and classified as follows:
• 首先，如果 E 是屬性或索引子存取，則會取得屬性或索引子存取的值（運算式的值），並將 E 重新分類為值。First, if E is a property or indexer access, then the value of the property or indexer access is obtained (Values of expressions) and E is reclassified as a value.
• 如果 I 識別一個或多個方法，則結果會是具有 E之相關聯實例運算式的方法群組。If I identifies one or more methods, then the result is a method group with an associated instance expression of E. 如果指定了類型引數清單，則會使用它來呼叫泛型方法（方法調用）。If a type argument list was specified, it is used in calling a generic method (Method invocations).
• 如果 I 識別實例屬性，則為，If I identifies an instance property,
• 如果 EthisI 會識別不含 setter 的自動執行屬性（自動實作為屬性），而參考會在類別或結構類型 T的實常式序中發生; 然後，結果會是一個變數，也就是由 I 所指定的 T 實例中，由 this所指定之 auto 屬性的隱藏支援欄位。If E is this, I identifies an automatically implemented property (Automatically implemented properties) without a setter, and the reference occurs within an instance constructor for a class or struct type T, then the result is a variable, namely the hidden backing field for the auto-property given by I in the instance of T given by this.
• 否則，結果會是具有 E之相關聯實例運算式的屬性存取。Otherwise, the result is a property access with an associated instance expression of E.
• 如果 Tclass_type ，而 I 識別該class_type的實例欄位：If T is a class_type and I identifies an instance field of that class_type:
• 如果 E 的值為 null，則會擲回 System.NullReferenceExceptionIf the value of E is null, then a System.NullReferenceException is thrown.
• 否則，如果欄位是 readonly，而參考發生在宣告欄位之類別的實例（instance）（class）的方法之外，則結果會是值，也就是 E所參考物件中的欄位 I 值。Otherwise, if the field is readonly and the reference occurs outside an instance constructor of the class in which the field is declared, then the result is a value, namely the value of the field I in the object referenced by E.
• 否則，結果會是一個變數，也就是 E所參考物件中 I 欄位。Otherwise, the result is a variable, namely the field I in the object referenced by E.
• 如果 Tstruct_type ，而 I 識別該struct_type的實例欄位：If T is a struct_type and I identifies an instance field of that struct_type:
• 如果 E 是值，或如果 readonly 欄位，而參考出現在宣告該欄位之結構的實例函式外部，則結果會是值，也就是在 E所指定的結構實例中，欄位 I 的值。If E is a value, or if the field is readonly and the reference occurs outside an instance constructor of the struct in which the field is declared, then the result is a value, namely the value of the field I in the struct instance given by E.
• 否則，結果會是一個變數，也就是在 E所指定的結構實例中 I 的欄位。Otherwise, the result is a variable, namely the field I in the struct instance given by E.
• 如果 I 識別實例事件：If I identifies an instance event:
• 如果參考發生在宣告事件的類別或結構中，而事件是在沒有event_accessor_declarations事件）的情況下宣告，而且參考不會做為 +=-= 運算子的左邊，則 E.I 的處理方式就如同 I 為實例欄位一樣。If the reference occurs within the class or struct in which the event is declared, and the event was declared without event_accessor_declarations (Events), and the reference does not occur as the left-hand side of a += or -= operator, then E.I is processed exactly as if I was an instance field.
• 否則，結果會是具有 E之相關聯實例運算式的事件存取。Otherwise, the result is an event access with an associated instance expression of E.
• 否則，會嘗試處理 E.I 做為擴充方法調用（擴充方法調用）。Otherwise, an attempt is made to process E.I as an extension method invocation (Extension method invocations). 如果失敗，E.I 是不正確成員參考，而且發生系結時錯誤。If this fails, E.I is an invalid member reference, and a binding-time error occurs.

#### 相同的簡單名稱和類型名稱Identical simple names and type names

struct Color
{
public static readonly Color White = new Color(...);
public static readonly Color Black = new Color(...);

public Color Complement() {...}
}

class A
{
public Color Color;                // Field Color of type Color

void F() {
Color = Color.Black;           // References Color.Black static member
Color = Color.Complement();    // Invokes Complement() on Color field
}

static void G() {
Color c = Color.White;         // References Color.White static member
}
}


#### 文法多義性Grammar ambiguities

Simple_name簡單名稱）和member_access成員存取）的生產可能會增加運算式文法中的多義性。The productions for simple_name (Simple names) and member_access (Member access) can give rise to ambiguities in the grammar for expressions. 例如，語句：For example, the statement:

F(G<A,B>(7));


(  )  ]  }  :  ;  ,  .  ?  ==  !=  |  ^


F(G<A,B>(7));


F(G < A, B > 7);
F(G < A, B >> 7);


x = F < A > +y;


x = y is C<T> + z;


C<T> 的權杖會以type_argument_listnamespace_or_type_name來解讀。the tokens C<T> are interpreted as a namespace_or_type_name with a type_argument_list.

### 叫用運算式Invocation expressions

Invocation_expression用來叫用方法。An invocation_expression is used to invoke a method.

invocation_expression
: primary_expression '(' argument_list? ')'
;


• Primary_expression具有編譯時間類型 dynamicThe primary_expression has compile-time type dynamic.
• 選擇性argument_list的至少一個引數具有編譯時間類型 dynamic 而且primary_expression沒有委派類型。At least one argument of the optional argument_list has compile-time type dynamic and the primary_expression does not have a delegate type.

Invocation_expressionprimary_expression必須是方法群組或delegate_type的值。The primary_expression of an invocation_expression must be a method group or a value of a delegate_type. 如果primary_expression是方法群組，則invocation_expression是方法調用（方法調用）。If the primary_expression is a method group, the invocation_expression is a method invocation (Method invocations). 如果primary_expressiondelegate_type的值，則Invocation_expression是委派調用（委派調用）。If the primary_expression is a value of a delegate_type, the invocation_expression is a delegate invocation (Delegate invocations). 如果primary_expression不是方法群組，也不是delegate_type的值，則會發生系結時錯誤。If the primary_expression is neither a method group nor a value of a delegate_type, a binding-time error occurs.

• 如果invocation_expression叫用傳回 void的方法或委派，則結果為「無」。If the invocation_expression invokes a method or delegate that returns void, the result is nothing. 只有在statement_expression運算式語句）或lambda_expression （匿名函式運算式）的內容中，才允許分類為任何內容的運算式。An expression that is classified as nothing is permitted only in the context of a statement_expression (Expression statements) or as the body of a lambda_expression (Anonymous function expressions). 否則會發生系結時錯誤。Otherwise a binding-time error occurs.
• 否則，結果會是方法或委派所傳回之類型的值。Otherwise, the result is a value of the type returned by the method or delegate.

#### 方法調用Method invocations

M(A)形式之方法調用的系結時間處理，其中 M 是方法群組（可能包括type_argument_list），而 A 是選擇性的argument_list，其中包含下列步驟：The binding-time processing of a method invocation of the form M(A), where M is a method group (possibly including a type_argument_list), and A is an optional argument_list, consists of the following steps:

• 方法調用的一組候選方法會被結構化。The set of candidate methods for the method invocation is constructed. 針對與方法群組相關聯的每個方法 F MFor each method F associated with the method group M:
• 如果 F 不是泛型，則在下列情況中，F 是候選項：If F is non-generic, F is a candidate when:
• M 沒有類型引數清單，且M has no type argument list, and
• F 適用于 A （適用的函式成員）。F is applicable with respect to A (Applicable function member).
• 如果 F 是泛型，而且 M 沒有類型引數清單，則 F 在下列情況下是候選項：If F is generic and M has no type argument list, F is a candidate when:
• 型別推斷（型別推斷）成功、推斷呼叫的型別引數清單，以及Type inference (Type inference) succeeds, inferring a list of type arguments for the call, and
• 一旦推斷的型別引數取代為對應的方法型別參數，F 的參數清單中的所有結構化類型都滿足其條件約束（滿足條件約束），而 F 的參數清單則適用于 A （適用的函式成員）。Once the inferred type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (Satisfying constraints), and the parameter list of F is applicable with respect to A (Applicable function member).
• 如果 F 是泛型，而 M 包含型別引數清單，則 F 在下列情況下是候選項：If F is generic and M includes a type argument list, F is a candidate when:
• F 具有與類型引數清單中所提供相同的方法類型參數數目，而F has the same number of method type parameters as were supplied in the type argument list, and
• 一旦類型引數取代為對應的方法類型參數，F 的參數清單中的所有結構化類型都滿足其條件約束（滿足條件約束），而 F 的參數清單則適用于 A適用的函式成員）。Once the type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (Satisfying constraints), and the parameter list of F is applicable with respect to A (Applicable function member).
• 候選方法集合會縮小為僅包含來自最多衍生類型的方法：針對集合中 C.F 的每個方法，其中 C 是宣告方法 F 的類型，則會從集合中移除 C 的基底類型中宣告的所有方法。The set of candidate methods is reduced to contain only methods from the most derived types: For each method C.F in the set, where C is the type in which the method F is declared, all methods declared in a base type of C are removed from the set. 此外，如果 Cobject以外的類別類型，則在介面類別型中宣告的所有方法都會從集合中移除。Furthermore, if C is a class type other than object, all methods declared in an interface type are removed from the set. （第二個規則只有在方法群組是在具有 object 以外的有效基類和非空白的有效介面集的類型參數上進行成員查詢的結果時才會影響）。(This latter rule only has affect when the method group was the result of a member lookup on a type parameter having an effective base class other than object and a non-empty effective interface set.)
• 如果產生的候選方法集合是空的，則會放棄沿著下列步驟進行的進一步處理，並改為嘗試將調用當做擴充方法調用（擴充方法調用）來處理。If the resulting set of candidate methods is empty, then further processing along the following steps are abandoned, and instead an attempt is made to process the invocation as an extension method invocation (Extension method invocations). 如果失敗，則不存在任何適用的方法，而且會發生系結時錯誤。If this fails, then no applicable methods exist, and a binding-time error occurs.
• 候選方法集合的最佳方法是使用多載解析的多載解析規則來識別。The best method of the set of candidate methods is identified using the overload resolution rules of Overload resolution. 如果無法識別單一最佳方法，則方法調用不明確，且會發生系結時錯誤。If a single best method cannot be identified, the method invocation is ambiguous, and a binding-time error occurs. 執行多載解析時，泛型方法的參數會在取代對應方法類型參數的類型引數（提供或推斷）之後考慮。When performing overload resolution, the parameters of a generic method are considered after substituting the type arguments (supplied or inferred) for the corresponding method type parameters.
• 會執行所選最佳方法的最終驗證：Final validation of the chosen best method is performed:
• 方法會在方法群組的內容中進行驗證：如果最佳方法是靜態方法，則方法群組必須從simple_name或透過類型的member_access產生。The method is validated in the context of the method group: If the best method is a static method, the method group must have resulted from a simple_name or a member_access through a type. 如果最佳方法是實例方法，則方法群組必須從simple_name、透過變數或值的member_access ，或base_access產生。If the best method is an instance method, the method group must have resulted from a simple_name, a member_access through a variable or value, or a base_access. 如果這兩項需求都不成立，就會發生系結時錯誤。If neither of these requirements is true, a binding-time error occurs.
• 如果最佳方法是泛型方法，則會根據泛型方法上所宣告的條件約束（滿足條件約束）來檢查類型引數（提供或推斷）。If the best method is a generic method, the type arguments (supplied or inferred) are checked against the constraints (Satisfying constraints) declared on the generic method. 如果任何類型引數不符合類型參數上的對應條件約束，就會發生系結時錯誤。If any type argument does not satisfy the corresponding constraint(s) on the type parameter, a binding-time error occurs.

#### 擴充方法調用Extension method invocations

expr . identifier ( )

expr . identifier ( args )

expr . identifier < typeargs > ( )

expr . identifier < typeargs > ( args )


C . identifier ( expr )

C . identifier ( expr , args )

C . identifier < typeargs > ( expr )

C . identifier < typeargs > ( expr , args )


Ci.Mj 的擴充方法符合下列條件An extension method Ci.Mj is eligible if:

• Ci 是非泛型、非嵌套的類別Ci is a non-generic, non-nested class
• Mj 的名稱是identifierThe name of Mj is identifier
• 套用至引數當做靜態方法（如上所示）時，可以存取並適用 MjMj is accessible and applicable when applied to the arguments as a static method as shown above
• exprMj的第一個參數型別都有隱含的識別、參考或裝箱轉換。An implicit identity, reference or boxing conversion exists from expr to the type of the first parameter of Mj.

• 從最接近的封入命名空間宣告開始，繼續進行每個封入的命名空間宣告，並以包含的編譯單位結束，後續嘗試會尋找一組候選的延伸方法：Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods:
• 如果指定的命名空間或編譯單位直接包含 Ci 具有合格擴充方法 Mj的非泛型型別宣告，則這些擴充方法的集合會是候選集合。If the given namespace or compilation unit directly contains non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.
• 如果類型 Ciusing_static_declarations匯入，而且在指定的命名空間或編譯 Mj單位中由using_namespace_directives 所匯入的命名空間中直接宣告，則這些擴充方法的集合會是候選集合。If types Ci imported by using_static_declarations and directly declared in namespaces imported by using_namespace_directives in the given namespace or compilation unit directly contain eligible extension methods Mj, then the set of those extension methods is the candidate set.
• 如果在任何封閉式命名空間宣告或編譯單位中找不到候選集合，則會發生編譯時期錯誤。If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs.
• 否則，多載解析會套用至候選集合，如（多載解析）中所述。Otherwise, overload resolution is applied to the candidate set as described in (Overload resolution). 如果找不到單一的最佳方法，就會發生編譯時期錯誤。If no single best method is found, a compile-time error occurs.
• C 是將最佳方法宣告為擴充方法的類型。C is the type within which the best method is declared as an extension method.

public static class E
{
public static void F(this object obj, int i) { }

public static void F(this object obj, string s) { }
}

class A { }

class B
{
public void F(int i) { }
}

class C
{
public void F(object obj) { }
}

class X
{
static void Test(A a, B b, C c) {
a.F(1);              // E.F(object, int)
a.F("hello");        // E.F(object, string)

b.F(1);              // B.F(int)
b.F("hello");        // E.F(object, string)

c.F(1);              // C.F(object)
c.F("hello");        // C.F(object)
}
}


public static class C
{
public static void F(this int i) { Console.WriteLine("C.F({0})", i); }
public static void G(this int i) { Console.WriteLine("C.G({0})", i); }
public static void H(this int i) { Console.WriteLine("C.H({0})", i); }
}

namespace N1
{
public static class D
{
public static void F(this int i) { Console.WriteLine("D.F({0})", i); }
public static void G(this int i) { Console.WriteLine("D.G({0})", i); }
}
}

namespace N2
{
using N1;

public static class E
{
public static void F(this int i) { Console.WriteLine("E.F({0})", i); }
}

class Test
{
static void Main(string[] args)
{
1.F();
2.G();
3.H();
}
}
}


E.F(1)
D.G(2)
C.H(3)


D.G 優先于 C.GE.F 優先于 D.FC.FD.G takes precedence over C.G, and E.F takes precedence over both D.F and C.F.

#### 委派調用Delegate invocations

D(A)形式的委派調用的執行時間處理，其中 Ddelegate_typeprimary_expression ，而 A 是選擇性的argument_list，其中包含下列步驟：The run-time processing of a delegate invocation of the form D(A), where D is a primary_expression of a delegate_type and A is an optional argument_list, consists of the following steps:

• 評估 DD is evaluated. 如果此評估導致例外狀況，則不會執行任何進一步的步驟。If this evaluation causes an exception, no further steps are executed.
• 已檢查 D 的值為有效。The value of D is checked to be valid. 如果 D 的值為 null，則會擲回 System.NullReferenceException，而且不會執行任何進一步的步驟。If the value of D is null, a System.NullReferenceException is thrown and no further steps are executed.
• 否則，D 是委派實例的參考。Otherwise, D is a reference to a delegate instance. 函式成員調用（動態多載解析的編譯階段檢查）會在委派的調用清單中的每個可呼叫實體上執行。Function member invocations (Compile-time checking of dynamic overload resolution) are performed on each of the callable entities in the invocation list of the delegate. 對於由實例和實例方法所組成的可呼叫實體，調用的實例是包含在可呼叫實體中的實例。For callable entities consisting of an instance and instance method, the instance for the invocation is the instance contained in the callable entity.

### 元素存取Element access

Element_accessprimary_no_array_creation_expression組成，後面接著 "[" token，後面接著argument_list，後面接著 "]" 權杖。An element_access consists of a primary_no_array_creation_expression, followed by a "[" token, followed by an argument_list, followed by a "]" token. Argument_list由一個或多個引數s 組成，並以逗號分隔。The argument_list consists of one or more arguments, separated by commas.

element_access
: primary_no_array_creation_expression '[' expression_list ']'
;


Element_accessargument_list不能包含 refout 引數。The argument_list of an element_access is not allowed to contain ref or out arguments.

• Primary_no_array_creation_expression具有編譯時間類型 dynamicThe primary_no_array_creation_expression has compile-time type dynamic.
• Argument_list的至少一個運算式具有編譯時間型別 dynamic，而primary_no_array_creation_expression沒有陣列型別。At least one expression of the argument_list has compile-time type dynamic and the primary_no_array_creation_expression does not have an array type.

#### 陣列存取Array access

P[A]格式之陣列存取的執行時間處理，其中 Parray_typeprimary_no_array_creation_expression ，而 A 是一個argument_list，其中包含下列步驟：The run-time processing of an array access of the form P[A], where P is a primary_no_array_creation_expression of an array_type and A is an argument_list, consists of the following steps:

• 評估 PP is evaluated. 如果此評估導致例外狀況，則不會執行任何進一步的步驟。If this evaluation causes an exception, no further steps are executed.
• Argument_list的索引運算式會依照順序（由左至右）進行評估。The index expressions of the argument_list are evaluated in order, from left to right. 遵循每個索引運算式的評估，會執行隱含轉換（隱含轉換）為下列其中一種類型： intuintlongulongFollowing evaluation of each index expression, an implicit conversion (Implicit conversions) to one of the following types is performed: int, uint, long, ulong. 選擇此清單中的第一個類型，其隱含轉換存在。The first type in this list for which an implicit conversion exists is chosen. 例如，如果索引運算式的類型是 short 則會執行隱含轉換成 int，因為從 short 隱含轉換到 int，以及從 shortlong 都是可行的。For instance, if the index expression is of type short then an implicit conversion to int is performed, since implicit conversions from short to int and from short to long are possible. 如果索引運算式的評估或後續的隱含轉換造成例外狀況，則不會評估進一步的索引運算式，也不會執行任何進一步的步驟。If evaluation of an index expression or the subsequent implicit conversion causes an exception, then no further index expressions are evaluated and no further steps are executed.
• 已檢查 P 的值為有效。The value of P is checked to be valid. 如果 P 的值為 null，則會擲回 System.NullReferenceException，而且不會執行任何進一步的步驟。If the value of P is null, a System.NullReferenceException is thrown and no further steps are executed.
• Argument_list中每個運算式的值都會針對 P所參考陣列實例的每個維度的實際界限進行檢查。The value of each expression in the argument_list is checked against the actual bounds of each dimension of the array instance referenced by P. 如果一個或多個值超出範圍，則會擲回 System.IndexOutOfRangeException，且不會執行任何進一步的步驟。If one or more values are out of range, a System.IndexOutOfRangeException is thrown and no further steps are executed.
• 索引運算式所指定之陣列元素的位置會計算出來，而此位置會成為陣列存取的結果。The location of the array element given by the index expression(s) is computed, and this location becomes the result of the array access.

#### 索引子存取Indexer access

P[A]形式的索引子存取的系結時間處理，其中 P 是類別、結構或介面類別型 Tprimary_no_array_creation_expression ，而 Aargument_list，其中包含下列步驟：The binding-time processing of an indexer access of the form P[A], where P is a primary_no_array_creation_expression of a class, struct, or interface type T, and A is an argument_list, consists of the following steps:

• T 所提供的索引子集合。The set of indexers provided by T is constructed. 此集合包含 T 中宣告的所有索引子，或不是 override 宣告的 T 基底類型，而且可在目前的內容中存取（成員存取）。The set consists of all indexers declared in T or a base type of T that are not override declarations and are accessible in the current context (Member access).
• 此集合會縮減為適用且不會被其他索引子隱藏的索引子。The set is reduced to those indexers that are applicable and not hidden by other indexers. 下列規則會套用至集合中的每個索引子 S.I，其中 S 是用來宣告索引子 I 的類型：The following rules are applied to each indexer S.I in the set, where S is the type in which the indexer I is declared:
• 如果 I 不適用於 A （適用的函式成員），則 I 會從集合中移除。If I is not applicable with respect to A (Applicable function member), then I is removed from the set.
• 如果 I 適用于 A （適用的函式成員），則會從集合中移除 S 基底類型中宣告的所有索引子。If I is applicable with respect to A (Applicable function member), then all indexers declared in a base type of S are removed from the set.
• 如果 I 適用于 A （適用的函式成員），而 Sobject以外的類別類型，則會從集合中移除在介面中宣告的所有索引子。If I is applicable with respect to A (Applicable function member) and S is a class type other than object, all indexers declared in an interface are removed from the set.
• 如果候選索引子的結果集是空的，則不會有適用的索引子存在，而且會發生系結時錯誤。If the resulting set of candidate indexers is empty, then no applicable indexers exist, and a binding-time error occurs.
• 候選索引子集合的最佳索引子是使用多載解析的多載解析規則來識別。The best indexer of the set of candidate indexers is identified using the overload resolution rules of Overload resolution. 如果無法識別單一的最佳索引子，則索引子存取是不明確的，而且會發生系結時錯誤。If a single best indexer cannot be identified, the indexer access is ambiguous, and a binding-time error occurs.
• Argument_list的索引運算式會依照順序（由左至右）進行評估。The index expressions of the argument_list are evaluated in order, from left to right. 處理索引子存取的結果是分類為索引子存取的運算式。The result of processing the indexer access is an expression classified as an indexer access. 索引子存取運算式會參考上述步驟中判斷的索引子，並具有 P 的相關聯實例運算式，以及 A的相關聯引數清單。The indexer access expression references the indexer determined in the step above, and has an associated instance expression of P and an associated argument list of A.

### 此存取權This access

This_access包含保留字 thisA this_access consists of the reserved word this.

this_access
: 'this'
;


• this 用於類別之實例函式內的primary_expression時，它會分類為值。When this is used in a primary_expression within an instance constructor of a class, it is classified as a value. 值的類型是發生使用之類別的實例類型（實例類型），而值則是所要建立之物件的參考。The type of the value is the instance type (The instance type) of the class within which the usage occurs, and the value is a reference to the object being constructed.
• this 用於類別的實例方法或實例存取子中的primary_expression時，它會分類為值。When this is used in a primary_expression within an instance method or instance accessor of a class, it is classified as a value. 值的類型是發生使用之類別的實例類型（實例類型），而值則是對其叫用方法或存取子之物件的參考。The type of the value is the instance type (The instance type) of the class within which the usage occurs, and the value is a reference to the object for which the method or accessor was invoked.
• this 用於結構之實例函式內的primary_expression時，它會分類為變數。When this is used in a primary_expression within an instance constructor of a struct, it is classified as a variable. 變數的類型是發生使用之結構的實例類型（實例類型），而變數則代表所要建立的結構。The type of the variable is the instance type (The instance type) of the struct within which the usage occurs, and the variable represents the struct being constructed. 結構之實例函式的 this 變數的行為與結構類型的 out 參數完全相同，特別是這表示變數必須在實例的每個執行路徑中明確指派。The this variable of an instance constructor of a struct behaves exactly the same as an out parameter of the struct type—in particular, this means that the variable must be definitely assigned in every execution path of the instance constructor.
• this 用於結構之實例方法或實例存取子中的primary_expression時，它會分類為變數。When this is used in a primary_expression within an instance method or instance accessor of a struct, it is classified as a variable. 變數的類型是發生使用之結構的實例類型（實例類型）。The type of the variable is the instance type (The instance type) of the struct within which the usage occurs.
• 如果方法或存取子不是反覆運算器（iterator），則 this 變數代表已叫用方法或存取子的結構，且其行為與結構類型的 ref 參數完全相同。If the method or accessor is not an iterator (Iterators), the this variable represents the struct for which the method or accessor was invoked, and behaves exactly the same as a ref parameter of the struct type.
• 如果方法或存取子是反覆運算器，則 this 變數代表已叫用方法或存取子的結構複本，其行為與結構類型的值參數完全相同。If the method or accessor is an iterator, the this variable represents a copy of the struct for which the method or accessor was invoked, and behaves exactly the same as a value parameter of the struct type.

### 基底存取Base access

Base_access包含保留字 base 後面接著「.」標記和識別碼，或是以方括弧括住的argument_listA base_access consists of the reserved word base followed by either a "." token and an identifier or an argument_list enclosed in square brackets:

base_access
: 'base' '.' identifier
| 'base' '[' expression_list ']'
;


Base_access可用來存取在目前類別或結構中以類似方式命名的成員所隱藏的基類成員。A base_access is used to access base class members that are hidden by similarly named members in the current class or struct. 只有在實例的的區塊、實例方法或實例存取子中，才允許base_accessA base_access is permitted only in the block of an instance constructor, an instance method, or an instance accessor. base.I 發生在類別或結構中時，I 必須代表該類別或結構之基類的成員。When base.I occurs in a class or struct, I must denote a member of the base class of that class or struct. 同樣地，當 base[E] 發生在類別中時，適用的索引子必須存在於基類中。Likewise, when base[E] occurs in a class, an applicable indexer must exist in the base class.

base_access參考虛擬函式成員（方法、屬性或索引子）時，會在執行時間（動態多載解析的編譯階段檢查）上判斷要叫用的函式成員已變更。When a base_access references a virtual function member (a method, property, or indexer), the determination of which function member to invoke at run-time (Compile-time checking of dynamic overload resolution) is changed. 所叫用的函式成員是藉由尋找與 B 相關之函式成員的最衍生實（虛擬方法）來決定（而不是針對 this的執行時間型別，如同平常在非基底存取中一般）。The function member that is invoked is determined by finding the most derived implementation (Virtual methods) of the function member with respect to B (instead of with respect to the run-time type of this, as would be usual in a non-base access). 因此，在 virtual 函式成員的 override 中， base_access可以用來叫用函式成員的繼承實作用。Thus, within an override of a virtual function member, a base_access can be used to invoke the inherited implementation of the function member. 如果base_access所參考的函式成員是抽象的，則會發生系結時錯誤。If the function member referenced by a base_access is abstract, a binding-time error occurs.

### 後置遞增和遞減運算子Postfix increment and decrement operators

post_increment_expression
: primary_expression '++'
;

post_decrement_expression
: primary_expression '--'
;


x++x-- 格式的後置遞增或遞減運算的執行時間處理包含下列步驟：The run-time processing of a postfix increment or decrement operation of the form x++ or x-- consists of the following steps:

• 如果 x 分類為變數：If x is classified as a variable:
• 評估 x 以產生變數。x is evaluated to produce the variable.
• 會儲存 x 的值。The value of x is saved.
• 會叫用選取的運算子，並將 x 的儲存值當做其引數。The selected operator is invoked with the saved value of x as its argument.
• 運算子所傳回的值會儲存在評估 x所指定的位置。The value returned by the operator is stored in the location given by the evaluation of x.
• 儲存的 x 值會變成作業的結果。The saved value of x becomes the result of the operation.
• 如果 x 分類為屬性或索引子存取：If x is classified as a property or indexer access:
• 實例運算式（如果 x 不是 static），而且會評估與 x 相關聯的引數清單（如果 x 是索引子存取），而結果會用於後續的 getset 存取子調用。The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent get and set accessor invocations.
• 會叫用 xget 存取子，並儲存傳回的值。The get accessor of x is invoked and the returned value is saved.
• 會叫用選取的運算子，並將 x 的儲存值當做其引數。The selected operator is invoked with the saved value of x as its argument.
• xset 存取子會以運算子所傳回的值做為其 value 引數來叫用。The set accessor of x is invoked with the value returned by the operator as its value argument.
• 儲存的 x 值會變成作業的結果。The saved value of x becomes the result of the operation.

++-- 運算子也支援前置詞標記法（前置遞增和遞減運算子）。The ++ and -- operators also support prefix notation (Prefix increment and decrement operators). 一般來說，x++x-- 的結果是作業之前 x 的值，而 ++x--x 的結果是作業之後 x 的值。Typically, the result of x++ or x-- is the value of x before the operation, whereas the result of ++x or --x is the value of x after the operation. 不論是哪一種情況，在作業之後，x 本身都具有相同的值。In either case, x itself has the same value after the operation.

### new 運算子The new operator

new 運算子是用來建立類型的新實例。The new operator is used to create new instances of types.

• 物件建立運算式是用來建立類別類型和實數值型別的新實例。Object creation expressions are used to create new instances of class types and value types.
• 陣列建立運算式是用來建立陣列類型的新實例。Array creation expressions are used to create new instances of array types.
• 委派建立運算式是用來建立委派類型的新實例。Delegate creation expressions are used to create new instances of delegate types.

new 運算子意指建立類型的實例，但不一定會隱含記憶體的動態配置。The new operator implies creation of an instance of a type, but does not necessarily imply dynamic allocation of memory. 特別是，實數值型別的實例不需要超過其所在變數的額外記憶體，而且當 new 用來建立實數值型別的實例時，並不會發生動態配置。In particular, instances of value types require no additional memory beyond the variables in which they reside, and no dynamic allocations occur when new is used to create instances of value types.

#### 物件建立運算式Object creation expressions

Object_creation_expression可用來建立class_typevalue_type的新實例。An object_creation_expression is used to create a new instance of a class_type or a value_type.

object_creation_expression
: 'new' type '(' argument_list? ')' object_or_collection_initializer?
| 'new' type object_or_collection_initializer
;

object_or_collection_initializer
: object_initializer
| collection_initializer
;


Object_creation_expression類型必須是class_typevalue_typetype_parameterThe type of an object_creation_expression must be a class_type, a value_type or a type_parameter. 類型不能是 abstract class_typeThe type cannot be an abstract class_type.

• 如果 Tvalue_type ，而且 A 不存在：If T is a value_type and A is not present:
• Object_creation_expression是預設的函式呼叫。The object_creation_expression is a default constructor invocation. Object_creation_expression的結果是 T類型的值，也就是在system.object 類型中定義的 T 預設值。The result of the object_creation_expression is a value of type T, namely the default value for T as defined in The System.ValueType type.
• 否則，如果 Ttype_parameter ，而且 A 不存在：Otherwise, if T is a type_parameter and A is not present:
• 如果未針對 T指定實數值型別條件約束或函式條件約束（類型參數條件約束），則會發生系結時錯誤。If no value type constraint or constructor constraint (Type parameter constraints) has been specified for T, a binding-time error occurs.
• Object_creation_expression的結果是型別參數已系結的執行時間型別值，也就是叫用該型別的預設函式的結果。The result of the object_creation_expression is a value of the run-time type that the type parameter has been bound to, namely the result of invoking the default constructor of that type. 執行時間類型可以是參考型別或實數值型別。The run-time type may be a reference type or a value type.
• 否則，如果 Tclass_typestruct_typeOtherwise, if T is a class_type or a struct_type:
• 如果 Tabstract class_type，就會發生編譯時期錯誤。If T is an abstract class_type, a compile-time error occurs.
• 要叫用的實例函式是使用多載解析的多載解析規則來決定。The instance constructor to invoke is determined using the overload resolution rules of Overload resolution. 候選實例的集合是由 T 中宣告的所有可存取的實例函式所組成，這些函式都適用于 A （適用的函式成員）。The set of candidate instance constructors consists of all accessible instance constructors declared in T which are applicable with respect to A (Applicable function member). 如果候選實例的集合是空的，或者無法識別單一最佳實例的函式，則會發生系結時錯誤。If the set of candidate instance constructors is empty, or if a single best instance constructor cannot be identified, a binding-time error occurs.
• Object_creation_expression的結果是 T類型的值，也就是叫用上述步驟中所決定之實例的函式所產生的值。The result of the object_creation_expression is a value of type T, namely the value produced by invoking the instance constructor determined in the step above.
• 否則， object_creation_expression無效，而且發生系結時錯誤。Otherwise, the object_creation_expression is invalid, and a binding-time error occurs.

• 如果 Tclass_typeIf T is a class_type:
• 已配置類別 T 的新實例。A new instance of class T is allocated. 如果沒有足夠的記憶體可配置新的實例，則會擲回 System.OutOfMemoryException，且不會執行任何進一步的步驟。If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
• 新實例的所有欄位都會初始化為其預設值（預設值）。All fields of the new instance are initialized to their default values (Default values).
• 根據函式成員調用的規則叫用實例的函式（動態多載解析的編譯時間檢查）。The instance constructor is invoked according to the rules of function member invocation (Compile-time checking of dynamic overload resolution). 新配置之實例的參考會自動傳遞至實例的函式，而且可以從該函式內以 this的方式存取實例。A reference to the newly allocated instance is automatically passed to the instance constructor and the instance can be accessed from within that constructor as this.
• 如果 Tstruct_typeIf T is a struct_type:
• T 類型的實例是藉由配置暫存區域變數來建立的。An instance of type T is created by allocating a temporary local variable. 因為struct_type的具現化程式必須明確地將值指派給所建立之實例的每個欄位，所以不需要初始化暫存變數。Since an instance constructor of a struct_type is required to definitely assign a value to each field of the instance being created, no initialization of the temporary variable is necessary.
• 根據函式成員調用的規則叫用實例的函式（動態多載解析的編譯時間檢查）。The instance constructor is invoked according to the rules of function member invocation (Compile-time checking of dynamic overload resolution). 新配置之實例的參考會自動傳遞至實例的函式，而且可以從該函式內以 this的方式存取實例。A reference to the newly allocated instance is automatically passed to the instance constructor and the instance can be accessed from within that constructor as this.

#### 物件初始設定式Object initializers

object_initializer
: '{' member_initializer_list? '}'
| '{' member_initializer_list ',' '}'
;

member_initializer_list
: member_initializer (',' member_initializer)*
;

member_initializer
: initializer_target '=' initializer_value
;

initializer_target
: identifier
| '[' argument_list ']'
;

initializer_value
: expression
| object_or_collection_initializer
;


public class Point
{
int x, y;

public int X { get { return x; } set { x = value; } }
public int Y { get { return y; } set { y = value; } }
}


Point 的實例可以建立和初始化，如下所示：An instance of Point can be created and initialized as follows:

Point a = new Point { X = 0, Y = 1 };


Point __a = new Point();
__a.X = 0;
__a.Y = 1;
Point a = __a;


public class Rectangle
{
Point p1, p2;

public Point P1 { get { return p1; } set { p1 = value; } }
public Point P2 { get { return p2; } set { p2 = value; } }
}


Rectangle 的實例可以建立和初始化，如下所示：An instance of Rectangle can be created and initialized as follows:

Rectangle r = new Rectangle {
P1 = new Point { X = 0, Y = 1 },
P2 = new Point { X = 2, Y = 3 }
};


Rectangle __r = new Rectangle();
Point __p1 = new Point();
__p1.X = 0;
__p1.Y = 1;
__r.P1 = __p1;
Point __p2 = new Point();
__p2.X = 2;
__p2.Y = 3;
__r.P2 = __p2;
Rectangle r = __r;


public class Rectangle
{
Point p1 = new Point();
Point p2 = new Point();

public Point P1 { get { return p1; } }
public Point P2 { get { return p2; } }
}


Rectangle r = new Rectangle {
P1 = { X = 0, Y = 1 },
P2 = { X = 2, Y = 3 }
};


Rectangle __r = new Rectangle();
__r.P1.X = 0;
__r.P1.Y = 1;
__r.P2.X = 2;
__r.P2.Y = 3;
Rectangle r = __r;


var c = new C {
x = true,
y = { a = "Hello" },
z = { 1, 2, 3 },
["x"] = 5,
[0,0] = { "a", "b" },
[1,2] = {}
};


C __c = new C();
__c.x = true;
__c.y.a = "Hello";
string __i1 = "x";
__c[__i1] = 5;
int __i2 = 0, __i3 = 0;
int __i4 = 1, __i5 = 2;
var c = __c;


#### 集合初始設定式Collection initializers

collection_initializer
: '{' element_initializer_list '}'
| '{' element_initializer_list ',' '}'
;

element_initializer_list
: element_initializer (',' element_initializer)*
;

element_initializer
: non_assignment_expression
| '{' expression_list '}'
;

expression_list
: expression (',' expression)*
;


List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };


public class Contact
{
string name;
List<string> phoneNumbers = new List<string>();

public string Name { get { return name; } set { name = value; } }

public List<string> PhoneNumbers { get { return phoneNumbers; } }
}


List<Contact> 可以建立和初始化，如下所示：A List<Contact> can be created and initialized as follows:

var contacts = new List<Contact> {
new Contact {
Name = "Chris Smith",
PhoneNumbers = { "206-555-0101", "425-882-8080" }
},
new Contact {
Name = "Bob Harris",
PhoneNumbers = { "650-555-0199" }
}
};


var __clist = new List<Contact>();
Contact __c1 = new Contact();
__c1.Name = "Chris Smith";
Contact __c2 = new Contact();
__c2.Name = "Bob Harris";
var contacts = __clist;


#### 陣列建立運算式Array creation expressions

Array_creation_expression可用來建立array_type的新實例。An array_creation_expression is used to create a new instance of an array_type.

array_creation_expression
: 'new' non_array_type '[' expression_list ']' rank_specifier* array_initializer?
| 'new' array_type array_initializer
| 'new' rank_specifier array_initializer
;


new int[,] {{0, 1}, {2, 3}, {4, 5}}


new int[3, 2] {{0, 1}, {2, 3}, {4, 5}}


• Expression_list的維度長度運算式會依序從左至右評估。The dimension length expressions of the expression_list are evaluated in order, from left to right. 評估每個運算式之後，會對下列其中一種類型執行隱含轉換（隱含轉換）： intuintlongulongFollowing evaluation of each expression, an implicit conversion (Implicit conversions) to one of the following types is performed: int, uint, long, ulong. 選擇此清單中的第一個類型，其隱含轉換存在。The first type in this list for which an implicit conversion exists is chosen. 如果運算式的評估或後續的隱含轉換造成例外狀況，則不會評估進一步的運算式，也不會執行任何進一步的步驟。If evaluation of an expression or the subsequent implicit conversion causes an exception, then no further expressions are evaluated and no further steps are executed.
• 維度長度的計算值會依照下列方式進行驗證。The computed values for the dimension lengths are validated as follows. 如果一或多個值小於零，則會擲回 System.OverflowException，且不會執行任何進一步的步驟。If one or more of the values are less than zero, a System.OverflowException is thrown and no further steps are executed.
• 系統會配置具有給定維度長度的陣列實例。An array instance with the given dimension lengths is allocated. 如果沒有足夠的記憶體可配置新的實例，則會擲回 System.OutOfMemoryException，且不會執行任何進一步的步驟。If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
• 新陣列實例的所有元素都會初始化為其預設值（預設值）。All elements of the new array instance are initialized to their default values (Default values).
• 如果陣列建立運算式包含陣列初始化運算式，則會評估陣列初始化運算式中的每個運算式，並將其指派給其對應的陣列元素。If the array creation expression contains an array initializer, then each expression in the array initializer is evaluated and assigned to its corresponding array element. 評估和指派會依照運算式在陣列初始化運算式中撰寫的順序來執行，換言之，專案會以遞增的索引順序初始化，而最右邊的維度會先遞增。The evaluations and assignments are performed in the order the expressions are written in the array initializer—in other words, elements are initialized in increasing index order, with the rightmost dimension increasing first. 如果給定運算式的評估或後續的對應陣列元素指派導致例外狀況，則不會初始化進一步的元素（因此其餘的專案將會有其預設值）。If evaluation of a given expression or the subsequent assignment to the corresponding array element causes an exception, then no further elements are initialized (and the remaining elements will thus have their default values).

int[][] a = new int[100][];


int[][] a = new int[100][5];        // Error


int[][] a = new int[100][];
for (int i = 0; i < 100; i++) a[i] = new int[5];


int[,] = new int[100, 5];


var a = new[] { 1, 10, 100, 1000 };                       // int[]

var b = new[] { 1, 1.5, 2, 2.5 };                         // double[]

var c = new[,] { { "hello", null }, { "world", "!" } };   // string[,]

var d = new[] { 1, "one", 2, "two" };                     // Error


var contacts = new[] {
new {
Name = "Chris Smith",
PhoneNumbers = new[] { "206-555-0101", "425-882-8080" }
},
new {
Name = "Bob Harris",
PhoneNumbers = new[] { "650-555-0199" }
}
};


#### 委派建立運算式Delegate creation expressions

Delegate_creation_expression可用來建立delegate_type的新實例。A delegate_creation_expression is used to create a new instance of a delegate_type.

delegate_creation_expression
: 'new' delegate_type '(' expression ')'
;


• 如果 E 是方法群組，則委派建立運算式的處理方式與從 ED的方法群組轉換（方法群組轉換）相同。If E is a method group, the delegate creation expression is processed in the same way as a method group conversion (Method group conversions) from E to D.
• 如果 E 是匿名函式，則會以從 ED的匿名函式轉換（匿名函數轉換）相同的方式來處理委派建立運算式。If E is an anonymous function, the delegate creation expression is processed in the same way as an anonymous function conversion (Anonymous function conversions) from E to D.
• 如果 E 是值，E 必須與 D相容（委派宣告），而結果會參考與 E相同的調用清單之類型 D 新建立的委派。If E is a value, E must be compatible (Delegate declarations) with D, and the result is a reference to a newly created delegate of type D that refers to the same invocation list as E. 如果 ED不相容，就會發生編譯時期錯誤。If E is not compatible with D, a compile-time error occurs.

• 如果 E 是方法群組，則委派建立運算式會評估為從 ED的方法群組轉換（方法群組轉換）。If E is a method group, the delegate creation expression is evaluated as a method group conversion (Method group conversions) from E to D.
• 如果 E 是匿名函式，則會將委派建立評估為從 ED 的匿名函式轉換（匿名函式轉換）。If E is an anonymous function, the delegate creation is evaluated as an anonymous function conversion from E to D (Anonymous function conversions).
• 如果 Edelegate_type的值：If E is a value of a delegate_type:
• 評估 EE is evaluated. 如果此評估導致例外狀況，則不會執行任何進一步的步驟。If this evaluation causes an exception, no further steps are executed.
• 如果 E 的值為 null，則會擲回 System.NullReferenceException，而且不會執行任何進一步的步驟。If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.
• 已配置 D 委派類型的新實例。A new instance of the delegate type D is allocated. 如果沒有足夠的記憶體可配置新的實例，則會擲回 System.OutOfMemoryException，且不會執行任何進一步的步驟。If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
• 新的委派實例會使用與 E所指定的委派實例相同的調用清單進行初始化。The new delegate instance is initialized with the same invocation list as the delegate instance given by E.

delegate double DoubleFunc(double x);

class A
{
DoubleFunc f = new DoubleFunc(Square);

static float Square(float x) {
return x * x;
}

static double Square(double x) {
return x * x;
}
}


A.f 欄位會使用參考第二個 Square 方法的委派進行初始化，因為該方法完全符合 DoubleFunc的型式參數清單和傳回類型。the A.f field is initialized with a delegate that refers to the second Square method because that method exactly matches the formal parameter list and return type of DoubleFunc. 如果第二個 Square 方法不存在，就會發生編譯時期錯誤。Had the second Square method not been present, a compile-time error would have occurred.

#### 匿名物件建立運算式Anonymous object creation expressions

Anonymous_object_creation_expression是用來建立匿名型別的物件。An anonymous_object_creation_expression is used to create an object of an anonymous type.

anonymous_object_creation_expression
: 'new' anonymous_object_initializer
;

anonymous_object_initializer
: '{' member_declarator_list? '}'
| '{' member_declarator_list ',' '}'
;

member_declarator_list
: member_declarator (',' member_declarator)*
;

member_declarator
: simple_name
| member_access
| base_access
| null_conditional_member_access
| identifier '=' expression
;


new { p1 = e1, p2 = e2, ..., pn = en }


class __Anonymous1
{
...

public __Anonymous1(T1 a1, T2 a2, ..., Tn an) {
f1 = a1;
f2 = a2;
...
fn = an;
}

public T1 p1 { get { return f1; } }
public T2 p2 { get { return f2; } }
...
public Tn pn { get { return fn; } }

public override bool Equals(object __o) { ... }
public override int GetHashCode() { ... }
}


var p1 = new { Name = "Lawnmower", Price = 495.00 };
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;


identifier
expr.identifier


identifier = identifier
identifier = expr.identifier


### Typeof 運算子The typeof operator

typeof 運算子是用來取得類型的 System.Type 物件。The typeof operator is used to obtain the System.Type object for a type.

typeof_expression
: 'typeof' '(' type ')'
| 'typeof' '(' unbound_type_name ')'
| 'typeof' '(' 'void' ')'
;

unbound_type_name
: identifier generic_dimension_specifier?
| identifier '::' identifier generic_dimension_specifier?
| unbound_type_name '.' identifier generic_dimension_specifier?
;

generic_dimension_specifier
: '<' comma* '>'
;

comma
: ','
;


Typeof_expression的第一種形式是由 typeof 關鍵字後面接著加上括弧的別所組成。The first form of typeof_expression consists of a typeof keyword followed by a parenthesized type. 此表單的運算式結果為所指定類型的 System.Type 物件。The result of an expression of this form is the System.Type object for the indicated type. 針對任何指定的類型，只有一個 System.Type 物件。There is only one System.Type object for any given type. 這表示對於類型 Ttypeof(T) == typeof(T) 一律為 true。This means that for a type T, typeof(T) == typeof(T) is always true. 無法 dynamic類型The type cannot be dynamic.

• 將每個generic_dimension_specifier換成type_name ，方法是以具有相同數目之逗號和關鍵字 objecttype_argument_list取代每個type_argumentConvert the sequence of tokens to a type_name by replacing each generic_dimension_specifier with a type_argument_list having the same number of commas and the keyword object as each type_argument.
• 評估產生的type_name，同時忽略所有類型參數條件約束。Evaluate the resulting type_name, while ignoring all type parameter constraints.
• Unbound_type_name會解析為與產生的結構化類型（系結和未系結類型）相關聯的未系結泛型型別。The unbound_type_name resolves to the unbound generic type associated with the resulting constructed type (Bound and unbound types).

Typeof_expression的結果是產生的未系結泛型型別的 System.Type 物件。The result of the typeof_expression is the System.Type object for the resulting unbound generic type.

typeof 運算子可用於類型參數。The typeof operator can be used on a type parameter. 結果是系結至型別參數之執行時間類型的 System.Type 物件。The result is the System.Type object for the run-time type that was bound to the type parameter. typeof 運算子也可以用於結構化類型或未系結的泛型型別（系結和未系結的類型）。The typeof operator can also be used on a constructed type or an unbound generic type (Bound and unbound types). 未系結泛型型別的 System.Type 物件與實例類型的 System.Type 物件不同。The System.Type object for an unbound generic type is not the same as the System.Type object of the instance type. 實例型別在執行時間一律是封閉的結構化型別，因此它的 System.Type 物件取決於使用中的執行時間型別引數，而未系結的泛型型別沒有型別引數。The instance type is always a closed constructed type at run-time so its System.Type object depends on the run-time type arguments in use, while the unbound generic type has no type arguments.

using System;

class X<T>
{
public static void PrintTypes() {
Type[] t = {
typeof(int),
typeof(System.Int32),
typeof(string),
typeof(double[]),
typeof(void),
typeof(T),
typeof(X<T>),
typeof(X<X<T>>),
typeof(X<>)
};
for (int i = 0; i < t.Length; i++) {
Console.WriteLine(t[i]);
}
}
}

class Test
{
static void Main() {
X<int>.PrintTypes();
}
}


System.Int32
System.Int32
System.String
System.Double[]
System.Void
System.Int32
X1[System.Int32]
X1[X1[System.Int32]]
X1[T]


### checked 和 unchecked 運算子The checked and unchecked operators

checkedunchecked 運算子可用來控制整數類型算數運算和轉換的溢位檢查內容The checked and unchecked operators are used to control the overflow checking context for integral-type arithmetic operations and conversions.

checked_expression
: 'checked' '(' expression ')'
;

unchecked_expression
: 'unchecked' '(' expression ')'
;


checked 運算子會在檢查的內容中評估包含的運算式，而 unchecked 運算子會在未檢查的內容中評估包含的運算式。The checked operator evaluates the contained expression in a checked context, and the unchecked operator evaluates the contained expression in an unchecked context. Checked_expressionunchecked_expression會完全對應至parenthesized_expression （加上括弧的運算式），不同之處在于包含的運算式會在給定的溢位檢查內容中進行評估。A checked_expression or unchecked_expression corresponds exactly to a parenthesized_expression (Parenthesized expressions), except that the contained expression is evaluated in the given overflow checking context.

• 當運算元為整數類資料類型時，預先定義的 ++-- 一元運算子（後置遞增和遞減運算子前置遞增和遞減運算子）。The predefined ++ and -- unary operators (Postfix increment and decrement operators and Prefix increment and decrement operators), when the operand is of an integral type.
• 當運算元為整數類資料類型時，預先定義的 - 一元運算子（一元減號運算子）。The predefined - unary operator (Unary minus operator), when the operand is of an integral type.
• 當兩個運算元都是整數類資料類型時，預先定義的 +-*/ 二元運算子（算術運算子）。The predefined +, -, *, and / binary operators (Arithmetic operators), when both operands are of integral types.
• 明確數值轉換（明確數值轉換），從一個整數類型到另一個整數類型，或從 floatdouble 到整數類資料類型。Explicit numeric conversions (Explicit numeric conversions) from one integral type to another integral type, or from float or double to an integral type.

• checked 內容中，如果作業是常數運算式（常數運算式），就會發生編譯時期錯誤。In a checked context, if the operation is a constant expression (Constant expressions), a compile-time error occurs. 否則，當作業在執行時間執行時，就會擲回 System.OverflowExceptionOtherwise, when the operation is performed at run-time, a System.OverflowException is thrown.
• unchecked 內容中，會捨棄不符合目的地類型的任何高序位位，以截斷結果。In an unchecked context, the result is truncated by discarding any high-order bits that do not fit in the destination type.

class Test
{
static readonly int x = 1000000;
static readonly int y = 1000000;

static int F() {
return checked(x * y);      // Throws OverflowException
}

static int G() {
return unchecked(x * y);    // Returns -727379968
}

static int H() {
return x * y;               // Depends on default
}
}


class Test
{
const int x = 1000000;
const int y = 1000000;

static int F() {
return checked(x * y);      // Compile error, overflow
}

static int G() {
return unchecked(x * y);    // Returns -727379968
}

static int H() {
return x * y;               // Compile error, overflow
}
}


checkedunchecked 運算子只會影響以程式形式包含在「(」和「)」標記內之作業的溢位檢查內容。The checked and unchecked operators only affect the overflow checking context for those operations that are textually contained within the "(" and ")" tokens. 運算子在評估包含的運算式時，不會對叫用的函式成員造成影響。The operators have no effect on function members that are invoked as a result of evaluating the contained expression. 在範例中In the example

class Test
{
static int Multiply(int x, int y) {
return x * y;
}

static int F() {
return checked(Multiply(1000000, 1000000));
}
}


F 中使用 checked 不會影響 Multiply中的 x * y 評估，因此會在預設溢位檢查內容中評估 x * ythe use of checked in F does not affect the evaluation of x * y in Multiply, so x * y is evaluated in the default overflow checking context.

class Test
{
public const int AllBits = unchecked((int)0xFFFFFFFF);

public const int HighBit = unchecked((int)0x80000000);
}


checkedunchecked 運算子和語句可讓程式設計人員控制某些數值計算的某些層面。The checked and unchecked operators and statements allow programmers to control certain aspects of some numeric calculations. 不過，某些數值運算子的行為取決於其運算元的資料類型。However, the behavior of some numeric operators depends on their operands' data types. 例如，兩個小數位數一律會導致溢位例外狀況，即使在明確 unchecked 的結構內也是如此。For example, multiplying two decimals always results in an exception on overflow even within an explicitly unchecked construct. 同樣地，即使在明確 checked 的結構中，將兩個浮點數相乘也不會造成溢位例外狀況。Similarly, multiplying two floats never results in an exception on overflow even within an explicitly checked construct. 此外，其他運算子絕不會受到檢查模式的影響，不論是預設或明確。In addition, other operators are never affected by the mode of checking, whether default or explicit.

### 預設值運算式Default value expressions

default_value_expression
: 'default' '(' type ')'
;


### Nameof 運算式Nameof expressions

Nameof_expression是用來取得程式實體的名稱，做為常數位串。A nameof_expression is used to obtain the name of a program entity as a constant string.

nameof_expression
: 'nameof' '(' named_entity ')'
;

named_entity
: simple_name
| named_entity_target '.' identifier type_argument_list?
;

named_entity_target
: 'this'
| 'base'
| named_entity
| predefined_type
| qualified_alias_member
;


Nameof_expressionnamed_entity意義就是運算式的意義;也就是simple_namebase_accessmember_accessThe meaning of the named_entity of a nameof_expression is the meaning of it as an expression; that is, either as a simple_name, a base_access or a member_access. 不過，在簡單名稱成員存取中所述的查閱會導致錯誤，因為在靜態內容中找到實例成員， nameof_expression不會產生這類錯誤。However, where the lookup described in Simple names and Member access results in an error because an instance member was found in a static context, a nameof_expression produces no such error.

Named_entity指定方法群組具有type_argument_list時，就會發生編譯時期錯誤。It is a compile-time error for a named_entity designating a method group to have a type_argument_list. Named_entity_target具有類型 dynamic時，就會發生編譯時期錯誤。It is a compile time error for a named_entity_target to have the type dynamic.

Nameof_expressionstring類型的常數運算式，而且在執行時間沒有任何作用。A nameof_expression is a constant expression of type string, and has no effect at runtime. 具體而言，它的named_entity不會進行評估，而且會因明確指派分析（簡單運算式的一般規則）而被忽略。Specifically, its named_entity is not evaluated, and is ignored for the purposes of definite assignment analysis (General rules for simple expressions). 其值是選擇性的最後type_argument_list之前named_entity的最後一個識別碼，以下列方式轉換：Its value is the last identifier of the named_entity before the optional final type_argument_list, transformed in the following way:

• 已移除前置詞 "@" （如果使用的話）。The prefix "@", if used, is removed.
• 每個unicode_escape_sequence都會轉換成其對應的 unicode 字元。Each unicode_escape_sequence is transformed into its corresponding Unicode character.
• 任何formatting_characters都會移除。Any formatting_characters are removed.

TODO：範例TODO: examples

### 匿名方法運算式Anonymous method expressions

Anonymous_method_expression是定義匿名函式的兩個方法之一。An anonymous_method_expression is one of two ways of defining an anonymous function. 這些會在匿名函數運算式中進一步說明。These are further described in Anonymous function expressions.

## 一元運算子Unary operators

?+-!~++--、cast 和 await 運算子稱為一元運算子。The ?, +, -, !, ~, ++, --, cast, and await operators are called the unary operators.

unary_expression
: primary_expression
| null_conditional_expression
| '+' unary_expression
| '-' unary_expression
| '!' unary_expression
| '~' unary_expression
| pre_increment_expression
| pre_decrement_expression
| cast_expression
| await_expression
| unary_expression_unsafe
;


### Null-條件運算子Null-conditional operator

Null 條件運算子只有在該運算元不是 null 時，才會將作業清單套用至其運算元。The null-conditional operator applies a list of operations to its operand only if that operand is non-null. 否則，套用運算子的結果會是 nullOtherwise the result of applying the operator is null.

null_conditional_expression
: primary_expression null_conditional_operations
;

null_conditional_operations
: null_conditional_operations? '?' '.' identifier type_argument_list?
| null_conditional_operations? '?' '[' argument_list ']'
| null_conditional_operations '.' identifier type_argument_list?
| null_conditional_operations '[' argument_list ']'
| null_conditional_operations '(' argument_list? ')'
;


E0E1 用來判斷 E的意義：E0 and E1 are used to determine the meaning of E:

• 如果 E 發生statement_expression E 的意義與語句相同If E occurs as a statement_expression the meaning of E is the same as the statement

if ((object)P != null) E1;


但只會評估 P 一次。except that P is evaluated only once.

• 否則，如果 E0 分類為不會發生編譯時期錯誤。Otherwise, if E0 is classified as nothing a compile-time error occurs.

• 否則，讓 T0E0的類型。Otherwise, let T0 be the type of E0.

• 如果 T0 是不知道是參考型別或不可為 null 的實數值型別的類型參數，則會發生編譯時期錯誤。If T0 is a type parameter that is not known to be a reference type or a non-nullable value type, a compile-time error occurs.

• 如果 T0 是不可為 null 的實數值型別，則會 T0?E 的類型，而 E 的意義會與If T0 is a non-nullable value type, then the type of E is T0?, and the meaning of E is the same as

((object)P == null) ? (T0?)null : E1


但只會評估 P 一次。except that P is evaluated only once.

• 否則，E 的類型為 T0，而 E 的意義則與Otherwise the type of E is T0, and the meaning of E is the same as

((object)P == null) ? null : E1


但只會評估 P 一次。except that P is evaluated only once.

a.b?[0]?.c();


if (a.b != null) a.b[0]?.c();


if (a.b != null) if (a.b[0] != null) a.b[0].c();


var x = a.b?[0]?.c();


var x = (a.b == null) ? null : (a.b[0] == null) ? null : a.b[0].c();


#### Null-條件運算式做為投影初始化運算式Null-conditional expressions as projection initializers

Null 條件運算式只能做為anonymous_object_creation_expression匿名物件建立運算式）中的member_declarator （如果其結尾為（選擇性的 null 條件式）成員存取）。A null-conditional expression is only allowed as a member_declarator in an anonymous_object_creation_expression (Anonymous object creation expressions) if it ends with an (optionally null-conditional) member access. 文法而言，這項需求可以表示為：Grammatically, this requirement can be expressed as:

null_conditional_member_access
: primary_expression null_conditional_operations? '?' '.' identifier type_argument_list?
| primary_expression null_conditional_operations '.' identifier type_argument_list?
;


#### Null-條件運算式做為語句運算式Null-conditional expressions as statement expressions

Null 條件運算式只有在以調用結尾時，才允許做為statement_expression運算式語句）。A null-conditional expression is only allowed as a statement_expression (Expression statements) if it ends with an invocation. 文法而言，這項需求可以表示為：Grammatically, this requirement can be expressed as:

null_conditional_invocation_expression
: primary_expression null_conditional_operations '(' argument_list? ')'
;


### 一元加號運算子Unary plus operator

int operator +(int x);
uint operator +(uint x);
long operator +(long x);
ulong operator +(ulong x);
float operator +(float x);
double operator +(double x);
decimal operator +(decimal x);


### 一元減號運算子Unary minus operator

• 整數否定：Integer negation:

int operator -(int x);
long operator -(long x);


藉由從零減去 x 來計算結果。The result is computed by subtracting x from zero. 如果 x 的值是運算元類型的最小可顯示值（int 為-2 ^ 31，而 long則為-2 ^ 63），則不會在運算元類型內顯示 x 的數學否定。If the value of x is the smallest representable value of the operand type (-2^31 for int or -2^63 for long), then the mathematical negation of x is not representable within the operand type. 如果這發生在 checked 內容中，則會擲回 System.OverflowException;如果它發生在 unchecked 內容中，則結果會是運算元的值，而且不會報告溢位。If this occurs within a checked context, a System.OverflowException is thrown; if it occurs within an unchecked context, the result is the value of the operand and the overflow is not reported.

如果負運算子的運算元屬於類型 uint，它會轉換成類型 long，而結果的類型會是 longIf the operand of the negation operator is of type uint, it is converted to type long, and the type of the result is long. 例外狀況是允許將 int 值-2147483648 （-2 ^ 31）寫入為十進位整數常值（整數常值）的規則。An exception is the rule that permits the int value -2147483648 (-2^31) to be written as a decimal integer literal (Integer literals).

如果負運算子的運算元屬於 ulong類型，就會發生編譯時期錯誤。If the operand of the negation operator is of type ulong, a compile-time error occurs. 例外狀況是允許 long 值-9223372036854775808 （-2 ^ 63）寫入為十進位整數常值（整數常值）的規則。An exception is the rule that permits the long value -9223372036854775808 (-2^63) to be written as a decimal integer literal (Integer literals).

• 浮點否定：Floating-point negation:

float operator -(float x);
double operator -(double x);


結果是 x 的值及其正負號反轉。The result is the value of x with its sign inverted. 如果 x 是 NaN，則結果也是 NaN。If x is NaN, the result is also NaN.

• 十進位數否定：Decimal negation:

decimal operator -(decimal x);


藉由從零減去 x 來計算結果。The result is computed by subtracting x from zero. 小數否定相當於使用 System.Decimal類型的一元減號運算子。Decimal negation is equivalent to using the unary minus operator of type System.Decimal.

### 邏輯否定運算子Logical negation operator

bool operator !(bool x);


### 位補數運算子Bitwise complement operator

int operator ~(int x);
uint operator ~(uint x);
long operator ~(long x);
ulong operator ~(ulong x);


E operator ~(E x);


### 前置遞增和遞減運算子Prefix increment and decrement operators

pre_increment_expression
: '++' unary_expression
;

pre_decrement_expression
: '--' unary_expression
;


++x--x 格式之前置遞增或遞減運算的執行時間處理包含下列步驟：The run-time processing of a prefix increment or decrement operation of the form ++x or --x consists of the following steps:

• 如果 x 分類為變數：If x is classified as a variable:
• 評估 x 以產生變數。x is evaluated to produce the variable.
• 所選取的運算子會以 x 的值做為其引數來叫用。The selected operator is invoked with the value of x as its argument.
• 運算子所傳回的值會儲存在評估 x所指定的位置。The value returned by the operator is stored in the location given by the evaluation of x.
• 運算子傳回的值會變成運算的結果。The value returned by the operator becomes the result of the operation.
• 如果 x 分類為屬性或索引子存取：If x is classified as a property or indexer access:
• 實例運算式（如果 x 不是 static），而且會評估與 x 相關聯的引數清單（如果 x 是索引子存取），而結果會用於後續的 getset 存取子調用。The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent get and set accessor invocations.
• 會叫用 xget 存取子。The get accessor of x is invoked.
• 所選取的運算子會以 get 存取子所傳回的值做為其引數來叫用。The selected operator is invoked with the value returned by the get accessor as its argument.
• xset 存取子會以運算子所傳回的值做為其 value 引數來叫用。The set accessor of x is invoked with the value returned by the operator as its value argument.
• 運算子傳回的值會變成運算的結果。The value returned by the operator becomes the result of the operation.

++-- 運算子也支援後置標記法（後置遞增和遞減運算子）。The ++ and -- operators also support postfix notation (Postfix increment and decrement operators). 一般來說，x++x-- 的結果是作業之前 x 的值，而 ++x--x 的結果是作業之後 x 的值。Typically, the result of x++ or x-- is the value of x before the operation, whereas the result of ++x or --x is the value of x after the operation. 不論是哪一種情況，在作業之後，x 本身都具有相同的值。In either case, x itself has the same value after the operation.

### Cast 運算式Cast expressions

Cast_expression是用來將運算式明確轉換成指定的型別。A cast_expression is used to explicitly convert an expression to a given type.

cast_expression
: '(' type ')' unary_expression
;


Cast_expression的文法會導致某些語法上的多義性。The grammar for a cast_expression leads to certain syntactic ambiguities. 例如，運算式 (x)-y 可以解讀為cast_expression-y 轉換為類型 x）或additive_expression結合 parenthesized_expression （這會計算x - y)For example, the expression (x)-y could either be interpreted as a cast_expression (a cast of -y to type x) or as an additive_expression combined with a parenthesized_expression (which computes the value x - y).

• Token 的順序是別的正確文法，而不是運算式The sequence of tokens is correct grammar for a type, but not for an expression.
• Token 的順序是正確的類型文法，而緊接在右括弧後面的標記是「~」、「!」、「token」、「(」、「識別碼Unicode 字元逸出序列）」、「值」（值），或除了 asis以外的任何關鍵字關鍵字）。The sequence of tokens is correct grammar for a type, and the token immediately following the closing parentheses is the token "~", the token "!", the token "(", an identifier (Unicode character escape sequences), a literal (Literals), or any keyword (Keywords) except as and is.

### Await 運算式Await expressions

Await 運算子是用來暫止封閉式非同步函式的評估，直到運算元所代表的非同步作業完成為止。The await operator is used to suspend evaluation of the enclosing async function until the asynchronous operation represented by the operand has completed.

await_expression
: 'await' unary_expression
;


• 在嵌套的（非非同步）匿名函式內Inside a nested (non-async) anonymous function
• lock_statement的區塊內Inside the block of a lock_statement
• 在不安全的內容中In an unsafe context

Await_expression的運算元稱為「工作」（ task）。The operand of an await_expression is called the task. 它代表在評估await_expression時，可能或不會完成的非同步作業。It represents an asynchronous operation that may or may not be complete at the time the await_expression is evaluated. Await 運算子的目的是暫停封閉式非同步函式的執行，直到等候的工作完成為止，然後取得其結果。The purpose of the await operator is to suspend execution of the enclosing async function until the awaited task is complete, and then obtain its outcome.

#### 可等候運算式Awaitable expressions

Await 運算式的工作必須是可等候The task of an await expression is required to be awaitable. 如果下列其中一個保留，則會可等候運算式 tAn expression t is awaitable if one of the following holds:

• t 是編譯時間類型 dynamict is of compile time type dynamic
• t 具有稱為 GetAwaiter 的可存取實例或擴充方法，沒有參數且沒有型別參數，以及下列所有的保留類型 At has an accessible instance or extension method called GetAwaiter with no parameters and no type parameters, and a return type A for which all of the following hold:
• A 會實 System.Runtime.CompilerServices.INotifyCompletion 介面（也就是簡單明瞭的 INotifyCompletionA implements the interface System.Runtime.CompilerServices.INotifyCompletion (hereafter known as INotifyCompletion for brevity)
• A 具有類型的可存取、可讀取的實例屬性 IsCompleted boolA has an accessible, readable instance property IsCompleted of type bool
• A 具有可存取的實例方法 GetResult 沒有參數，而且沒有型別參數A has an accessible instance method GetResult with no parameters and no type parameters

GetAwaiter 方法的目的是要取得工作的awaiterThe purpose of the GetAwaiter method is to obtain an awaiter for the task. A 的類型稱為 await 運算式的awaiter 類型The type A is called the awaiter type for the await expression.

IsCompleted 屬性的目的是要判斷工作是否已完成。The purpose of the IsCompleted property is to determine if the task is already complete. 若是如此，就不需要暫停評估。If so, there is no need to suspend evaluation.

INotifyCompletion.OnCompleted 方法的目的是要註冊工作的「接續」;也就是工作完成後，將會叫用的委派（屬於 System.Action類型）。The purpose of the INotifyCompletion.OnCompleted method is to sign up a "continuation" to the task; i.e. a delegate (of type System.Action) that will be invoked once the task is complete.

GetResult 方法的目的是要在工作完成之後取得其結果。The purpose of the GetResult method is to obtain the outcome of the task once it is complete. 這項結果可能是成功完成（可能包含結果值），也可能是由 GetResult 方法擲回的例外狀況。This outcome may be successful completion, possibly with a result value, or it may be an exception which is thrown by the GetResult method.

#### Await 運算式的執行時間評估Runtime evaluation of await expressions

• Awaiter a 是藉由評估運算式 (t).GetAwaiter()來取得。An awaiter a is obtained by evaluating the expression (t).GetAwaiter().
• bool b 是藉由評估運算式 (a).IsCompleted來取得。A bool b is obtained by evaluating the expression (a).IsCompleted.
• 如果 bfalse 則評估會取決於 a 是否會執行介面 System.Runtime.CompilerServices.ICriticalNotifyCompletion （在此為簡潔起見，這稱為 ICriticalNotifyCompletion）。If b is false then evaluation depends on whether a implements the interface System.Runtime.CompilerServices.ICriticalNotifyCompletion (hereafter known as ICriticalNotifyCompletion for brevity). 這種檢查會在系結階段完成;也就是在執行時間，如果 a 在編譯時間類型 dynamic，則為，否則為。This check is done at binding time; i.e. at runtime if a has the compile time type dynamic, and at compile time otherwise. r 表示繼續委派（反覆運算器）：Let r denote the resumption delegate (Iterators):
• 如果 a 不會執行 ICriticalNotifyCompletion，則會評估運算式 (a as (INotifyCompletion)).OnCompleted(r)If a does not implement ICriticalNotifyCompletion, then the expression (a as (INotifyCompletion)).OnCompleted(r) is evaluated.
• 如果 a 執行 ICriticalNotifyCompletion，則會評估運算式 (a as (ICriticalNotifyCompletion)).UnsafeOnCompleted(r)If a does implement ICriticalNotifyCompletion, then the expression (a as (ICriticalNotifyCompletion)).UnsafeOnCompleted(r) is evaluated.
• 然後會暫止評估，並將控制權傳回給 async 函數目前的呼叫端。Evaluation is then suspended, and control is returned to the current caller of the async function.
• 緊接在（如果 btrue），或在稍後叫用繼續委派（如果 bfalse）之後，就會評估運算式 (a).GetResult()Either immediately after (if b was true), or upon later invocation of the resumption delegate (if b was false), the expression (a).GetResult() is evaluated. 如果它傳回值，該值就是await_expression的結果。If it returns a value, that value is the result of the await_expression. 否則，結果為 [無]。Otherwise the result is nothing.

Awaiter 的介面方法 INotifyCompletion.OnCompletedICriticalNotifyCompletion.UnsafeOnCompleted 的執行，應該會導致最多隻能叫用委派 r 一次。An awaiter's implementation of the interface methods INotifyCompletion.OnCompleted and ICriticalNotifyCompletion.UnsafeOnCompleted should cause the delegate r to be invoked at most once. 否則，封閉式非同步函式的行為會是未定義的。Otherwise, the behavior of the enclosing async function is undefined.

## 算術運算子Arithmetic operators

[*]、[/]、[%]、[+] 和 [-] 運算子稱為算術運算子。The *, /, %, +, and - operators are called the arithmetic operators.

multiplicative_expression
: unary_expression
| multiplicative_expression '*' unary_expression
| multiplicative_expression '/' unary_expression
| multiplicative_expression '%' unary_expression
;

: multiplicative_expression
;


### 乘法運算子Multiplication operator

• 整數乘法：Integer multiplication:

int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);


checked 內容中，如果產品超出結果類型的範圍，則會擲回 System.OverflowExceptionIn a checked context, if the product is outside the range of the result type, a System.OverflowException is thrown. unchecked 內容中，不會報告溢位，且會捨棄超出結果型別範圍的任何重要高序位位。In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

• 浮點乘法：Floating-point multiplication:

float operator *(float x, float y);
double operator *(double x, double y);


產品是根據 IEEE 754 算術的規則來計算。The product is computed according to the rules of IEEE 754 arithmetic. 下表列出非零的有限值、零、無限大和 NaN 的所有可能組合的結果。The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. 在資料表中，xy 是正的有限值。In the table, x and y are positive finite values. zx * y的結果。z is the result of x * y. 如果結果對目的地類型而言太大，z 為無限大。If the result is too large for the destination type, z is infinity. 如果結果太小而無法用於目的地類型，z 為零。If the result is too small for the destination type, z is zero.

+y+y -y-y +0+0 4.9.0--0 +inf+inf -inf-inf NaNNaN
+x+x + z+z -z-z +0+0 4.9.0--0 +inf+inf -inf-inf NaNNaN
-x-x -z-z + z+z 4.9.0--0 +0+0 -inf-inf +inf+inf NaNNaN
+0+0 +0+0 4.9.0--0 +0+0 4.9.0--0 NaNNaN NaNNaN NaNNaN
4.9.0--0 4.9.0--0 +0+0 4.9.0--0 +0+0 NaNNaN NaNNaN NaNNaN
+inf+inf +inf+inf -inf-inf NaNNaN NaNNaN +inf+inf -inf-inf NaNNaN
-inf-inf -inf-inf +inf+inf NaNNaN NaNNaN -inf-inf +inf+inf NaNNaN
NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
• Decimal 乘法：Decimal multiplication:

decimal operator *(decimal x, decimal y);


如果產生的值太大，而無法以 decimal 格式表示，則會擲回 System.OverflowExceptionIf the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 如果結果值太小而無法以 decimal 格式表示，則結果會是零。If the result value is too small to represent in the decimal format, the result is zero. 在任何進位之前，結果的小數位數是兩個運算元之刻度的總和。The scale of the result, before any rounding, is the sum of the scales of the two operands.

Decimal 乘法相當於使用 System.Decimal類型的乘法運算子。Decimal multiplication is equivalent to using the multiplication operator of type System.Decimal.

### 除法運算子Division operator

• 整數除法：Integer division:

int operator /(int x, int y);
uint operator /(uint x, uint y);
long operator /(long x, long y);
ulong operator /(ulong x, ulong y);


如果右運算元的值為零，則會擲回 System.DivideByZeroExceptionIf the value of the right operand is zero, a System.DivideByZeroException is thrown.

除法會將結果向零四捨五入。The division rounds the result towards zero. 因此，結果的絕對值是最大的可能整數，小於或等於兩個運算元的商的絕對值。Thus the absolute value of the result is the largest possible integer that is less than or equal to the absolute value of the quotient of the two operands. 當兩個運算元具有相同的正負號，而且兩個運算元具有相反正負號時，結果為零或正數。The result is zero or positive when the two operands have the same sign and zero or negative when the two operands have opposite signs.

如果左運算元是最小的可顯示 intlong 值，而且已 -1右運算元，則會發生溢位。If the left operand is the smallest representable int or long value and the right operand is -1, an overflow occurs. checked 內容中，這會擲回 System.ArithmeticException （或其子類別）。In a checked context, this causes a System.ArithmeticException (or a subclass thereof) to be thrown. unchecked 內容中，它會定義為是否擲回 System.ArithmeticException （或其子類別），否則會以左運算元的結果值來未報告溢位。In an unchecked context, it is implementation-defined as to whether a System.ArithmeticException (or a subclass thereof) is thrown or the overflow goes unreported with the resulting value being that of the left operand.

• 浮點除法：Floating-point division:

float operator /(float x, float y);
double operator /(double x, double y);


這些商是根據 IEEE 754 算術的規則來計算。The quotient is computed according to the rules of IEEE 754 arithmetic. 下表列出非零的有限值、零、無限大和 NaN 的所有可能組合的結果。The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. 在資料表中，xy 是正的有限值。In the table, x and y are positive finite values. zx / y的結果。z is the result of x / y. 如果結果對目的地類型而言太大，z 為無限大。If the result is too large for the destination type, z is infinity. 如果結果太小而無法用於目的地類型，z 為零。If the result is too small for the destination type, z is zero.

+y+y -y-y +0+0 4.9.0--0 +inf+inf -inf-inf NaNNaN
+x+x + z+z -z-z +inf+inf -inf-inf +0+0 4.9.0--0 NaNNaN
-x-x -z-z + z+z -inf-inf +inf+inf 4.9.0--0 +0+0 NaNNaN
+0+0 +0+0 4.9.0--0 NaNNaN NaNNaN +0+0 4.9.0--0 NaNNaN
4.9.0--0 4.9.0--0 +0+0 NaNNaN NaNNaN 4.9.0--0 +0+0 NaNNaN
+inf+inf +inf+inf -inf-inf +inf+inf -inf-inf NaNNaN NaNNaN NaNNaN
-inf-inf -inf-inf +inf+inf -inf-inf +inf+inf NaNNaN NaNNaN NaNNaN
NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
• 小數除法：Decimal division:

decimal operator /(decimal x, decimal y);


如果右運算元的值為零，則會擲回 System.DivideByZeroExceptionIf the value of the right operand is zero, a System.DivideByZeroException is thrown. 如果產生的值太大，而無法以 decimal 格式表示，則會擲回 System.OverflowExceptionIf the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 如果結果值太小而無法以 decimal 格式表示，則結果會是零。If the result value is too small to represent in the decimal format, the result is zero. 結果的規模是最小的尺規，會將結果與最接近的可顯示十進位值保持為實際的數學結果。The scale of the result is the smallest scale that will preserve a result equal to the nearest representable decimal value to the true mathematical result.

小數除法相當於使用 System.Decimal類型的除法運算子。Decimal division is equivalent to using the division operator of type System.Decimal.

### 餘數運算子Remainder operator

• 整數餘數：Integer remainder:

int operator %(int x, int y);
uint operator %(uint x, uint y);
long operator %(long x, long y);
ulong operator %(ulong x, ulong y);


x % y 的結果是由 x - (x / y) * y所產生的值。The result of x % y is the value produced by x - (x / y) * y. 如果 y 為零，則會擲回 System.DivideByZeroExceptionIf y is zero, a System.DivideByZeroException is thrown.

如果左運算元是最小的 intlong 值，而右運算元是 -1，則會擲回 System.OverflowExceptionIf the left operand is the smallest int or long value and the right operand is -1, a System.OverflowException is thrown. 在任何情況下，x % y 都會擲回例外狀況，其中 x / y 不會擲回例外狀況。In no case does x % y throw an exception where x / y would not throw an exception.

• 浮點餘數：Floating-point remainder:

float operator %(float x, float y);
double operator %(double x, double y);


下表列出非零的有限值、零、無限大和 NaN 的所有可能組合的結果。The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. 在資料表中，xy 是正的有限值。In the table, x and y are positive finite values. zx % y 的結果，而且會計算為 x - n * y，其中 n 是小於或等於 x / y的最大可能整數。z is the result of x % y and is computed as x - n * y, where n is the largest possible integer that is less than or equal to x / y. 這種計算餘數的方法類似于用於整數運算元的，但與 IEEE 754 定義不同（其中 n 是最接近 x / y的整數）。This method of computing the remainder is analogous to that used for integer operands, but differs from the IEEE 754 definition (in which n is the integer closest to x / y).

+y+y -y-y +0+0 4.9.0--0 +inf+inf -inf-inf NaNNaN
+x+x + z+z + z+z NaNNaN NaNNaN xx xx NaNNaN
-x-x -z-z -z-z NaNNaN NaNNaN -x-x -x-x NaNNaN
+0+0 +0+0 +0+0 NaNNaN NaNNaN +0+0 +0+0 NaNNaN
4.9.0--0 4.9.0--0 4.9.0--0 NaNNaN NaNNaN 4.9.0--0 4.9.0--0 NaNNaN
+inf+inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
-inf-inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
• 小數餘數：Decimal remainder:

decimal operator %(decimal x, decimal y);


如果右運算元的值為零，則會擲回 System.DivideByZeroExceptionIf the value of the right operand is zero, a System.DivideByZeroException is thrown. 在任何進位之前，結果的小數值會大於兩個運算元的刻度，而結果的正負號（如果不是零）則與 x相同。The scale of the result, before any rounding, is the larger of the scales of the two operands, and the sign of the result, if non-zero, is the same as that of x.

小數餘數相當於使用 System.Decimal類型的餘數運算子。Decimal remainder is equivalent to using the remainder operator of type System.Decimal.

int operator +(int x, int y);
uint operator +(uint x, uint y);
long operator +(long x, long y);
ulong operator +(ulong x, ulong y);


checked 內容中，如果總和超出結果類型的範圍，則會擲回 System.OverflowExceptionIn a checked context, if the sum is outside the range of the result type, a System.OverflowException is thrown. unchecked 內容中，不會報告溢位，且會捨棄超出結果型別範圍的任何重要高序位位。In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

float operator +(float x, float y);
double operator +(double x, double y);


總和是根據 IEEE 754 算術的規則來計算。The sum is computed according to the rules of IEEE 754 arithmetic. 下表列出非零的有限值、零、無限大和 NaN 的所有可能組合的結果。The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. 在資料表中，xy 是非零的有限值，而 zx + y的結果。In the table, x and y are nonzero finite values, and z is the result of x + y. 如果 xy 具有相同的大小，但正負號相反，則 z 為正零。If x and y have the same magnitude but opposite signs, z is positive zero. 如果 x + y 太大而無法在目的地類型中表示，z 就是具有與 x + y相同正負號的無限大。If x + y is too large to represent in the destination type, z is an infinity with the same sign as x + y.

Yy +0+0 4.9.0--0 +inf+inf -inf-inf NaNNaN
xx zz xx xx +inf+inf -inf-inf NaNNaN
+0+0 Yy +0+0 +0+0 +inf+inf -inf-inf NaNNaN
4.9.0--0 Yy +0+0 4.9.0--0 +inf+inf -inf-inf NaNNaN
+inf+inf +inf+inf +inf+inf +inf+inf +inf+inf NaNNaN NaNNaN
-inf-inf -inf-inf -inf-inf -inf-inf NaNNaN -inf-inf NaNNaN
NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN

decimal operator +(decimal x, decimal y);


如果產生的值太大，而無法以 decimal 格式表示，則會擲回 System.OverflowExceptionIf the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 在任何進位之前，結果的小數值會大於兩個運算元的刻度。The scale of the result, before any rounding, is the larger of the scales of the two operands.

Decimal 加法相當於使用 System.Decimal類型的加法運算子。Decimal addition is equivalent to using the addition operator of type System.Decimal.

• 列舉加法。Enumeration addition. 每個列舉型別都會隱含提供下列預先定義的運算子，其中 E 是列舉型別，而 UE的基礎型別：Every enumeration type implicitly provides the following predefined operators, where E is the enum type, and U is the underlying type of E:

E operator +(E x, U y);
E operator +(U x, E y);


在執行時間，這些運算子會完全依照 (E)((U)x + (U)y)進行評估。At run-time these operators are evaluated exactly as (E)((U)x + (U)y).

• 字串串連：String concatenation:

string operator +(string x, string y);
string operator +(string x, object y);
string operator +(object x, string y);


Binary + 運算子的這些多載會執行字串串連。These overloads of the binary + operator perform string concatenation. 如果 null字串串連的運算元，則會替代空字串。If an operand of string concatenation is null, an empty string is substituted. 否則，會叫用繼承自類型 object的虛擬 ToString 方法，將任何非字串引數轉換成其字串表示。Otherwise, any non-string argument is converted to its string representation by invoking the virtual ToString method inherited from type object. 如果 ToString 傳回 null，則會替代空字串。If ToString returns null, an empty string is substituted.

using System;

class Test
{
static void Main() {
string s = null;
Console.WriteLine("s = >" + s + "<");        // displays s = ><
int i = 1;
Console.WriteLine("i = " + i);               // displays i = 1
float f = 1.2300E+15F;
Console.WriteLine("f = " + f);               // displays f = 1.23E+15
decimal d = 2.900m;
Console.WriteLine("d = " + d);               // displays d = 2.900
}
}


字串串連運算子的結果是由左運算元的字元，後面接著右運算元的字元所組成的字串。 字串串連運算子永遠不會傳回 null 值。 如果沒有足夠的記憶體可用來配置產生的字串，則可能會擲回 System.OutOfMemoryExceptionA System.OutOfMemoryException may be thrown if there is not enough memory available to allocate the resulting string.

• 委派組合。Delegate combination. 每個委派類型都會隱含提供下列預先定義的運算子，其中 D 是委派類型：Every delegate type implicitly provides the following predefined operator, where D is the delegate type:

D operator +(D x, D y);


當兩個運算元都屬於 D的某些委派類型時，二元 + 運算子會執行委派組合。The binary + operator performs delegate combination when both operands are of some delegate type D. （如果運算元有不同的委派類型，就會發生系結時錯誤）。如果 null第一個運算元，則作業的結果會是第二個運算元的值（即使也 null）。(If the operands have different delegate types, a binding-time error occurs.) If the first operand is null, the result of the operation is the value of the second operand (even if that is also null). 否則，如果第二個運算元 null，運算的結果就是第一個運算元的值。Otherwise, if the second operand is null, then the result of the operation is the value of the first operand. 否則，作業的結果會是新的委派實例，當叫用時，會叫用第一個運算元，然後叫用第二個運算元。Otherwise, the result of the operation is a new delegate instance that, when invoked, invokes the first operand and then invokes the second operand. 如需委派組合的範例，請參閱減法運算子委派調用For examples of delegate combination, see Subtraction operator and Delegate invocation. 因為 System.Delegate 不是委派類型，所以不會為其定義 operator +Since System.Delegate is not a delegate type, operator + is not defined for it.

### 減法運算子Subtraction operator

• 整數減法：Integer subtraction:

int operator -(int x, int y);
uint operator -(uint x, uint y);
long operator -(long x, long y);
ulong operator -(ulong x, ulong y);


checked 內容中，如果差異超出結果類型的範圍，則會擲回 System.OverflowExceptionIn a checked context, if the difference is outside the range of the result type, a System.OverflowException is thrown. unchecked 內容中，不會報告溢位，且會捨棄超出結果型別範圍的任何重要高序位位。In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

• 浮點減法：Floating-point subtraction:

float operator -(float x, float y);
double operator -(double x, double y);


差異是根據 IEEE 754 算術的規則來計算。The difference is computed according to the rules of IEEE 754 arithmetic. 下表列出非零的有限值、零、無限大和 Nan 的所有可能組合的結果。The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaNs. 在資料表中，xy 是非零的有限值，而 zx - y的結果。In the table, x and y are nonzero finite values, and z is the result of x - y. 如果 xy 相等，z 為正零。If x and y are equal, z is positive zero. 如果 x - y 太大而無法在目的地類型中表示，z 就是具有與 x - y相同正負號的無限大。If x - y is too large to represent in the destination type, z is an infinity with the same sign as x - y.

Yy +0+0 4.9.0--0 +inf+inf -inf-inf NaNNaN
xx zz xx xx -inf-inf +inf+inf NaNNaN
+0+0 -y-y +0+0 +0+0 -inf-inf +inf+inf NaNNaN
4.9.0--0 -y-y 4.9.0--0 +0+0 -inf-inf +inf+inf NaNNaN
+inf+inf +inf+inf +inf+inf +inf+inf NaNNaN +inf+inf NaNNaN
-inf-inf -inf-inf -inf-inf -inf-inf -inf-inf NaNNaN NaNNaN
NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
• 十進位減法：Decimal subtraction:

decimal operator -(decimal x, decimal y);


如果產生的值太大，而無法以 decimal 格式表示，則會擲回 System.OverflowExceptionIf the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 在任何進位之前，結果的小數值會大於兩個運算元的刻度。The scale of the result, before any rounding, is the larger of the scales of the two operands.

十進位減法相當於使用 System.Decimal類型的減法運算子。Decimal subtraction is equivalent to using the subtraction operator of type System.Decimal.

• 列舉減法。Enumeration subtraction. 每個列舉型別都會隱含提供下列預先定義的運算子，其中 E 是列舉型別，而 UE的基礎型別：Every enumeration type implicitly provides the following predefined operator, where E is the enum type, and U is the underlying type of E:

U operator -(E x, E y);


這個運算子的評估方式會與 (U)((U)x - (U)y)完全相同。This operator is evaluated exactly as (U)((U)x - (U)y). 換句話說，運算子會計算 xy的序數值之間的差異，而結果的類型則是列舉的基礎類型。In other words, the operator computes the difference between the ordinal values of x and y, and the type of the result is the underlying type of the enumeration.

E operator -(E x, U y);


這個運算子的評估方式會與 (E)((U)x - y)完全相同。This operator is evaluated exactly as (E)((U)x - y). 換句話說，運算子會從列舉的基礎類型減去值，產生列舉的值。In other words, the operator subtracts a value from the underlying type of the enumeration, yielding a value of the enumeration.

• 委派移除。Delegate removal. 每個委派類型都會隱含提供下列預先定義的運算子，其中 D 是委派類型：Every delegate type implicitly provides the following predefined operator, where D is the delegate type:

D operator -(D x, D y);


當兩個運算元都屬於 D的某些委派類型時，二元 - 運算子會執行委派移除。The binary - operator performs delegate removal when both operands are of some delegate type D. 如果運算元有不同的委派類型，就會發生系結時錯誤。If the operands have different delegate types, a binding-time error occurs. 如果第一個運算元是 null，則作業的結果是 nullIf the first operand is null, the result of the operation is null. 否則，如果第二個運算元 null，運算的結果就是第一個運算元的值。Otherwise, if the second operand is null, then the result of the operation is the value of the first operand. 否則，這兩個運算元代表具有一或多個專案的調用清單（委派宣告），而結果是由第一個運算元的清單所組成的新調用清單，其中第二個運算元的專案已從它移除，但前提是第二個運算元的清單是第一個的適當連續子清單。Otherwise, both operands represent invocation lists (Delegate declarations) having one or more entries, and the result is a new invocation list consisting of the first operand's list with the second operand's entries removed from it, provided the second operand's list is a proper contiguous sublist of the first's. （若要判斷子清單是否相等，對應的專案會針對委派等號比較運算子（委派相等運算子）進行比對。）否則，結果會是左運算元的值。(To determine sublist equality, corresponding entries are compared as for the delegate equality operator (Delegate equality operators).) Otherwise, the result is the value of the left operand. 進程中的兩個運算元清單都不會變更。Neither of the operands' lists is changed in the process. 如果第二個運算元的清單符合第一個運算元清單中連續專案的多個 sublists，則會移除連續專案的最右邊相符子清單。If the second operand's list matches multiple sublists of contiguous entries in the first operand's list, the right-most matching sublist of contiguous entries is removed. 如果移除導致空白清單，則結果是 nullIf removal results in an empty list, the result is null. 例如：For example:

delegate void D(int x);

class C
{
public static void M1(int i) { /* ... */ }
public static void M2(int i) { /* ... */ }
}

class Test
{
static void Main() {
D cd1 = new D(C.M1);
D cd2 = new D(C.M2);
D cd3 = cd1 + cd2 + cd2 + cd1;   // M1 + M2 + M2 + M1
cd3 -= cd1;                      // => M1 + M2 + M2

cd3 = cd1 + cd2 + cd2 + cd1;     // M1 + M2 + M2 + M1
cd3 -= cd1 + cd2;                // => M2 + M1

cd3 = cd1 + cd2 + cd2 + cd1;     // M1 + M2 + M2 + M1
cd3 -= cd2 + cd2;                // => M1 + M1

cd3 = cd1 + cd2 + cd2 + cd1;     // M1 + M2 + M2 + M1
cd3 -= cd2 + cd1;                // => M1 + M2

cd3 = cd1 + cd2 + cd2 + cd1;     // M1 + M2 + M2 + M1
cd3 -= cd1 + cd1;                // => M1 + M2 + M2 + M1
}
}


## 移位運算子Shift operators

<<>> 運算子可用來執行位移位作業。The << and >> operators are used to perform bit shifting operations.

shift_expression
;


• 左移：Shift left:

int operator <<(int x, int count);
uint operator <<(uint x, int count);
long operator <<(long x, int count);
ulong operator <<(ulong x, int count);


<< 運算子會將 x 向左移位一些計算的位數，如下所述。The << operator shifts x left by a number of bits computed as described below.

系統會捨棄 x 結果類型範圍以外的高序位位，其餘的位會向左移動，而低序位的空白位位置會設定為零。The high-order bits outside the range of the result type of x are discarded, the remaining bits are shifted left, and the low-order empty bit positions are set to zero.

• 右移：Shift right:

int operator >>(int x, int count);
uint operator >>(uint x, int count);
long operator >>(long x, int count);
ulong operator >>(ulong x, int count);


>> 運算子會將 x 右移一些計算的位數，如下所述。The >> operator shifts x right by a number of bits computed as described below.

x 的類型為 intlong時，會捨棄 x 的低序位位，其餘的位會向右移，而如果 x 為負數，則高序位空白位位置會設定為零。When x is of type int or long, the low-order bits of x are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero if x is non-negative and set to one if x is negative.

x 的類型 uintulong時，會捨棄 x 的低序位位，其餘的位則會向右移動，而高序位空白位位置會設定為零。When x is of type uint or ulong, the low-order bits of x are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero.

• x 的類型 intuint時，移位元數目是由 count的低序位五位所提供。When the type of x is int or uint, the shift count is given by the low-order five bits of count. 換句話說，位移計數是從 count & 0x1F計算而來。In other words, the shift count is computed from count & 0x1F.
• x 類型 longulong時，位移計數是由 count的低序位六位所提供。When the type of x is long or ulong, the shift count is given by the low-order six bits of count. 換句話說，位移計數是從 count & 0x3F計算而來。In other words, the shift count is computed from count & 0x3F.

>> 運算子的左運算元是帶正負號的整數類資料類型時，運算子會執行算術移位，其中運算元的最高有效位（正負號位）值會傳播至高序位空白位位置。When the left operand of the >> operator is of a signed integral type, the operator performs an arithmetic shift right wherein the value of the most significant bit (the sign bit) of the operand is propagated to the high-order empty bit positions. >> 運算子的左運算元是不帶正負號的整數類資料類型時，運算子會執行邏輯移位，其中高順序的空白位位置一律會設定為零。When the left operand of the >> operator is of an unsigned integral type, the operator performs a logical shift right wherein high-order empty bit positions are always set to zero. 若要執行從運算元類型推斷而來的相反運算，可以使用明確轉換。To perform the opposite operation of that inferred from the operand type, explicit casts can be used. 例如，如果 xint類型的變數，則作業 unchecked((int)((uint)x >> y)) 會執行 x的邏輯移位許可權。For example, if x is a variable of type int, the operation unchecked((int)((uint)x >> y)) performs a logical shift right of x.

## 關係和類型測試運算子Relational and type-testing operators

==!=<><=>=isas 運算子稱為「關聯式」和「型別測試」運算子。The ==, !=, <, >, <=, >=, is and as operators are called the relational and type-testing operators.

relational_expression
: shift_expression
| relational_expression '<' shift_expression
| relational_expression '>' shift_expression
| relational_expression '<=' shift_expression
| relational_expression '>=' shift_expression
| relational_expression 'is' type
| relational_expression 'as' type
;

equality_expression
: relational_expression
| equality_expression '==' relational_expression
| equality_expression '!=' relational_expression
;


Is 運算子中描述了 is 運算子，而 as 運算子則會在as 運算子中描述。The is operator is described in The is operator and the as operator is described in The as operator.

==!=<><=>= 運算子都是比較運算子The ==, !=, <, >, <= and >= operators are comparison operators.

x == y true，如果 x 等於 y，則為，否則為 falsetrue if x is equal to y, false otherwise
x != y true 如果 x 不等於 y，則為，否則為 falsetrue if x is not equal to y, false otherwise
x < y true 如果 x 小於 y，則為，否則為 falsetrue if x is less than y, false otherwise
x > y true 如果 x 大於 y，則為，否則為 falsetrue if x is greater than y, false otherwise
x <= y true，如果 x 小於或等於 y，則為，否則為 falsetrue if x is less than or equal to y, false otherwise
x >= y true 如果 x 大於或等於 y，則為，否則為 falsetrue if x is greater than or equal to y, false otherwise

### 整數比較運算子Integer comparison operators

bool operator ==(int x, int y);
bool operator ==(uint x, uint y);
bool operator ==(long x, long y);
bool operator ==(ulong x, ulong y);

bool operator !=(int x, int y);
bool operator !=(uint x, uint y);
bool operator !=(long x, long y);
bool operator !=(ulong x, ulong y);

bool operator <(int x, int y);
bool operator <(uint x, uint y);
bool operator <(long x, long y);
bool operator <(ulong x, ulong y);

bool operator >(int x, int y);
bool operator >(uint x, uint y);
bool operator >(long x, long y);
bool operator >(ulong x, ulong y);

bool operator <=(int x, int y);
bool operator <=(uint x, uint y);
bool operator <=(long x, long y);
bool operator <=(ulong x, ulong y);

bool operator >=(int x, int y);
bool operator >=(uint x, uint y);
bool operator >=(long x, long y);
bool operator >=(ulong x, ulong y);


### 浮點比較運算子Floating-point comparison operators

bool operator ==(float x, float y);
bool operator ==(double x, double y);

bool operator !=(float x, float y);
bool operator !=(double x, double y);

bool operator <(float x, float y);
bool operator <(double x, double y);

bool operator >(float x, float y);
bool operator >(double x, double y);

bool operator <=(float x, float y);
bool operator <=(double x, double y);

bool operator >=(float x, float y);
bool operator >=(double x, double y);


• 如果任一個運算元是 NaN，則會針對 true結果的所有運算子（!=除外） false 結果。If either operand is NaN, the result is false for all operators except !=, for which the result is true. 對於任何兩個運算元，x != y 一律會產生與 !(x == y)相同的結果。For any two operands, x != y always produces the same result as !(x == y). 不過，當其中一個或兩個運算元都是 NaN 時，<><=>= 運算子並不會產生與相反運算子的邏輯否定相同的結果。However, when one or both operands are NaN, the <, >, <=, and >= operators do not produce the same results as the logical negation of the opposite operator. 例如，如果 xy 都是 NaN，則 x < yfalse，但 !(x >= y)trueFor example, if either of x and y is NaN, then x < y is false, but !(x >= y) is true.

• 當運算元都不是 NaN 時，運算子會比較兩個浮點運算元的值與排序有關When neither operand is NaN, the operators compare the values of the two floating-point operands with respect to the ordering

-inf < -max < ... < -min < -0.0 == +0.0 < +min < ... < +max < +inf


其中 minmax 是可以用指定的浮點格式表示的最小和最大的正有限值。where min and max are the smallest and largest positive finite values that can be represented in the given floating-point format. 此順序的值得注意的效果如下：Notable effects of this ordering are:

• 負和正零會視為相等。Negative and positive zeros are considered equal.
• 負無限大會被視為小於所有其他值，但等於另一個負無限大。A negative infinity is considered less than all other values, but equal to another negative infinity.
• 正無限大會視為大於所有其他值，但等於另一個正無限大。A positive infinity is considered greater than all other values, but equal to another positive infinity.

### 小數比較運算子Decimal comparison operators

bool operator ==(decimal x, decimal y);
bool operator !=(decimal x, decimal y);
bool operator <(decimal x, decimal y);
bool operator >(decimal x, decimal y);
bool operator <=(decimal x, decimal y);
bool operator >=(decimal x, decimal y);


### 布林等號比較運算子Boolean equality operators

bool operator ==(bool x, bool y);
bool operator !=(bool x, bool y);


### 列舉比較運算子Enumeration comparison operators

bool operator ==(E x, E y);
bool operator !=(E x, E y);
bool operator <(E x, E y);
bool operator >(E x, E y);
bool operator <=(E x, E y);
bool operator >=(E x, E y);


### 參考型別等號比較運算子Reference type equality operators

bool operator ==(object x, object y);
bool operator !=(object x, object y);


• 這兩個運算元都是已知為reference_type或常值 null的類型值。Both operands are a value of a type known to be a reference_type or the literal null. 此外，從任一運算元的類型到另一個運算元的類型，都有明確的參考轉換（明確參考轉換）。Furthermore, an explicit reference conversion (Explicit reference conversions) exists from the type of either operand to the type of the other operand.
• 一個運算元是類型 T 的值，其中 Ttype_parameter ，而另一個運算元則是常值 nullOne operand is a value of type T where T is a type_parameter and the other operand is the literal null. 此外 T 不具有實數值型別條件約束。Furthermore T does not have the value type constraint.

• 使用預先定義的參考型別等號比較運算子，在系結時，比較已知不同的兩個參考，是一種系結時錯誤。It is a binding-time error to use the predefined reference type equality operators to compare two references that are known to be different at binding-time. 例如，如果運算元的系結時間類型是 AB的兩個類別類型，而且如果沒有 AB 衍生自另一個，則這兩個運算元就無法參考相同的物件。For example, if the binding-time types of the operands are two class types A and B, and if neither A nor B derives from the other, then it would be impossible for the two operands to reference the same object. 因此，作業會被視為系結時錯誤。Thus, the operation is considered a binding-time error.
• 預先定義的參考型別相等運算子不允許比較實數值型別運算元。The predefined reference type equality operators do not permit value type operands to be compared. 因此，除非結構型別宣告它自己的等號比較運算子，否則不可能比較該結構型別的值。Therefore, unless a struct type declares its own equality operators, it is not possible to compare values of that struct type.
• 預先定義的參考型別等號比較運算子永遠不會對其運算元執行「裝箱」作業。The predefined reference type equality operators never cause boxing operations to occur for their operands. 執行這類的裝箱作業是沒有意義的，因為對新配置的已裝箱實例的參考，一定會與其他所有參考不同。It would be meaningless to perform such boxing operations, since references to the newly allocated boxed instances would necessarily differ from all other references.
• 如果類型參數類型的運算元 T 比較 null，而 T 的執行時間類型是實數值型別，則會 false比較的結果。If an operand of a type parameter type T is compared to null, and the run-time type of T is a value type, the result of the comparison is false.

class C<T>
{
void F(T x) {
if (x == null) throw new ArgumentNullException();
...
}
}


using System;

class Test
{
static void Main() {
string s = "Test";
string t = string.Copy(s);
Console.WriteLine(s == t);
Console.WriteLine((object)s == t);
Console.WriteLine(s == (object)t);
Console.WriteLine((object)s == (object)t);
}
}


True
False
False
False


st 變數指的是兩個不同的 string 實例，其中包含相同的字元。The s and t variables refer to two distinct string instances containing the same characters. 第一個比較會 True 輸出，因為兩個運算元都是 string類型時，會選取預先定義的字串相等運算子（字串等號比較運算子）。The first comparison outputs True because the predefined string equality operator (String equality operators) is selected when both operands are of type string. 其餘的所有輸出 False，因為當其中一個或兩個運算元都是 object類型時，會選取預先定義的參考型別等號比較運算子。The remaining comparisons all output False because the predefined reference type equality operator is selected when one or both of the operands are of type object.

class Test
{
static void Main() {
int i = 123;
int j = 123;
System.Console.WriteLine((object)i == (object)j);
}
}


### 字串等號比較運算子String equality operators

bool operator ==(string x, string y);
bool operator !=(string x, string y);


• 這兩個值都是 nullBoth values are null.
• 對於在每個字元位置具有相同長度和相同字元的字串實例而言，這兩個值都是非 null 參考。Both values are non-null references to string instances that have identical lengths and identical characters in each character position.

### 委派等號比較運算子Delegate equality operators

bool operator ==(System.Delegate x, System.Delegate y);
bool operator !=(System.Delegate x, System.Delegate y);


• 如果其中一個委派實例 null，只有在同時 null兩者時，才會相等。If either of the delegate instances is null, they are equal if and only if both are null.
• 如果委派有不同的執行時間類型，它們絕對不會相等。If the delegates have different run-time type they are never equal.
• 如果這兩個委派實例都有調用清單（委派宣告），只有在其調用清單的長度相同時，這些實例才會相等，而且在另一個調用清單中的每個專案都相等（如下面所定義）至對應的專案（依序）。If both of the delegate instances have an invocation list (Delegate declarations), those instances are equal if and only if their invocation lists are the same length, and each entry in one's invocation list is equal (as defined below) to the corresponding entry, in order, in the other's invocation list.

• 如果兩個調用清單專案都參考相同的靜態方法，則專案相等。If two invocation list entries both refer to the same static method then the entries are equal.
• 如果兩個調用清單專案都參考相同目標物件上的相同非靜態方法（如參考等號比較運算子所定義），則專案會相等。If two invocation list entries both refer to the same non-static method on the same target object (as defined by the reference equality operators) then the entries are equal.
• 在具有相同（可能是空的）集的已捕捉外部變數實例的情況中，會允許（但非必要）為相同的，從評估產生的調用清單專案anonymous_method_expressions 或lambda_expressions 是相等的。Invocation list entries produced from evaluation of semantically identical anonymous_method_expressions or lambda_expressions with the same (possibly empty) set of captured outer variable instances are permitted (but not required) to be equal.

### 等號比較運算子和 nullEquality operators and null

==!= 運算子允許一個運算元是可為 null 類型的值，另一個運算元則是 null 常值，即使作業沒有預先定義或使用者定義的運算子（unlifted 或提升形式）。The == and != operators permit one operand to be a value of a nullable type and the other to be the null literal, even if no predefined or user-defined operator (in unlifted or lifted form) exists for the operation.

x == null
null == x
x != null
null != x


### Is 運算子The is operator

is 運算子可用來動態檢查物件的執行時間類型是否與指定的類型相容。The is operator is used to dynamically check if the run-time type of an object is compatible with a given type. 作業 E is T的結果（其中 E 是運算式，而 T 是類型）是布林值，指出 E 是否可以透過參考轉換、裝箱轉換或取消裝箱轉換成功轉換成類型 TThe result of the operation E is T, where E is an expression and T is a type, is a boolean value indicating whether E can successfully be converted to type T by a reference conversion, a boxing conversion, or an unboxing conversion. 在將類型引數取代為所有類型參數之後，會依照下列方式評估作業：The operation is evaluated as follows, after type arguments have been substituted for all type parameters:

• 如果 E 是匿名函式，則會發生編譯時期錯誤If E is an anonymous function, a compile-time error occurs
• 如果 E 是方法群組或 null 常值，則如果 E 的類型是參考型別或可為 null 的類型，且 E 的值是 null，則結果為 false。If E is a method group or the null literal, of if the type of E is a reference type or a nullable type and the value of E is null, the result is false.
• 否則，讓 D 表示 E 的動態類型，如下所示：Otherwise, let D represent the dynamic type of E as follows:
• 如果 E 的類型是參考型別，D 就是 E實例參考的執行時間類型。If the type of E is a reference type, D is the run-time type of the instance reference by E.
• 如果 E 的型別是可為 null 的型別，D 就是該可為 null 型別的基礎型別。If the type of E is a nullable type, D is the underlying type of that nullable type.
• 如果 E 的型別是不可為 null 的實值型別，D 就是 E的型別。If the type of E is a non-nullable value type, D is the type of E.
• 作業的結果取決於 DT，如下所示：The result of the operation depends on D and T as follows:
• 如果 T 是參考型別，如果 DT 屬於相同類型，則結果為 true，如果 D 是參考型別，以及從 DT 存在的隱含參考轉換，或者 D 是實數值型別，且從 DT 的裝箱轉換存在。If T is a reference type, the result is true if D and T are the same type, if D is a reference type and an implicit reference conversion from D to T exists, or if D is a value type and a boxing conversion from D to T exists.
• 如果 T 是可為 null 的型別，則如果 DT的基礎類型，則結果為 true。If T is a nullable type, the result is true if D is the underlying type of T.
• 如果 T 是不可為 null 的實數值型別，則如果 DT 的類型相同，則結果為 true。If T is a non-nullable value type, the result is true if D and T are the same type.
• 否則，結果為 false。Otherwise, the result is false.

### As 運算子The as operator

as 運算子可用來將值明確轉換為指定的參考型別或可為 null 的型別。The as operator is used to explicitly convert a value to a given reference type or nullable type. 不同于 cast 運算式（cast運算式），as 運算子絕對不會擲回例外狀況。Unlike a cast expression (Cast expressions), the as operator never throws an exception. 相反地，如果不可能指定的轉換，則產生的值會是 nullInstead, if the indicated conversion is not possible, the resulting value is null.

E as T表單的作業中，E 必須是運算式，而且 T 必須是參考型別、已知為參考型別的類型參數，或可為 null 的類型。In an operation of the form E as T, E must be an expression and T must be a reference type, a type parameter known to be a reference type, or a nullable type. 此外，下列至少一項必須為 true，否則會發生編譯時期錯誤：Furthermore, at least one of the following must be true, or otherwise a compile-time error occurs:

E is T ? (T)(E) : (T)null


E is T ? (T)(object)(E) : (T)null


class X
{

public string F(object o) {
return o as string;        // OK, string is a reference type
}

public T G<T>(object o) where T: Attribute {
return o as T;             // Ok, T has a class constraint
}

public U H<U>(object o) {
return o as U;             // Error, U is unconstrained
}
}


G 的型別參數 T 已知為引用型別，因為它有類別條件約束。the type parameter T of G is known to be a reference type, because it has the class constraint. 不過，H 的型別參數 U 不是;因此，不允許在 H 中使用 as 運算子。The type parameter U of H is not however; hence the use of the as operator in H is disallowed.

## 邏輯運算子Logical operators

&^| 運算子稱為邏輯運算子。The &, ^, and | operators are called the logical operators.

and_expression
: equality_expression
| and_expression '&' equality_expression
;

exclusive_or_expression
: and_expression
| exclusive_or_expression '^' and_expression
;

inclusive_or_expression
: exclusive_or_expression
| inclusive_or_expression '|' exclusive_or_expression
;


### 整數邏輯運算子Integer logical operators

int operator &(int x, int y);
uint operator &(uint x, uint y);
long operator &(long x, long y);
ulong operator &(ulong x, ulong y);

int operator |(int x, int y);
uint operator |(uint x, uint y);
long operator |(long x, long y);
ulong operator |(ulong x, ulong y);

int operator ^(int x, int y);
uint operator ^(uint x, uint y);
long operator ^(long x, long y);
ulong operator ^(ulong x, ulong y);


& 運算子會計算兩個運算元的位邏輯 AND| 運算子會計算兩個運算元的位邏輯 OR，而 ^ 運算子會計算兩個運算元的位邏輯獨佔 ORThe & operator computes the bitwise logical AND of the two operands, the | operator computes the bitwise logical OR of the two operands, and the ^ operator computes the bitwise logical exclusive OR of the two operands. 這些作業不可能發生溢位。No overflows are possible from these operations.

### 列舉邏輯運算子Enumeration logical operators

E operator &(E x, E y);
E operator |(E x, E y);
E operator ^(E x, E y);


### 布林值邏輯運算子Boolean logical operators

bool operator &(bool x, bool y);
bool operator |(bool x, bool y);
bool operator ^(bool x, bool y);


xy 皆為 true，那麼 x & y 的結果會是 trueThe result of x & y is true if both x and y are true. 否則，結果為 falseOtherwise, the result is false.

### 可為 null 的布林值邏輯運算子Nullable boolean logical operators

bool? operator &(bool? x, bool? y);
bool? operator |(bool? x, bool? y);


x y x & y x | y
true true true true
true false false true
true null null true
false true false true
false false false false
false null false null
null true null true
null false false null
null null null null

## 條件邏輯運算子Conditional logical operators

&&|| 運算子稱為「條件式邏輯運算子」。The && and || operators are called the conditional logical operators. 它們也稱為「最小運算」邏輯運算子。They are also called the "short-circuiting" logical operators.

conditional_and_expression
: inclusive_or_expression
| conditional_and_expression '&&' inclusive_or_expression
;

conditional_or_expression
: conditional_and_expression
| conditional_or_expression '||' conditional_and_expression
;


&&|| 運算子是 &| 運算子的條件式版本：The && and || operators are conditional versions of the & and | operators:

• 作業 x && y 對應至 x & y的作業，但只有 xfalse時才會評估 yThe operation x && y corresponds to the operation x & y, except that y is evaluated only if x is not false.
• 作業 x || y 對應至 x | y的作業，但只有 xtrue時才會評估 yThe operation x || y corresponds to the operation x | y, except that y is evaluated only if x is not true.

x && yx || y 格式的作業會藉由套用多載解析（二元運算子多載解析）來處理，如同作業是以 x & yx | y的方式撰寫。An operation of the form x && y or x || y is processed by applying overload resolution (Binary operator overload resolution) as if the operation was written x & y or x | y. 如此一來，Then,

### 布林條件邏輯運算子Boolean conditional logical operators

&&|| 的運算元屬於 bool類型，或如果運算元的類型未定義適用的 operator &operator |，但確實定義了對 bool的隱含轉換，則會以下列方式處理作業：When the operands of && or || are of type bool, or when the operands are of types that do not define an applicable operator & or operator |, but do define implicit conversions to bool, the operation is processed as follows:

• x && y 的運算會評估為 x ? y : falseThe operation x && y is evaluated as x ? y : false. 換句話說，x 會先進行評估，並轉換成類型 boolIn other words, x is first evaluated and converted to type bool. 然後，如果 truexy 會進行評估並轉換成類型 bool，而這會成為作業的結果。Then, if x is true, y is evaluated and converted to type bool, and this becomes the result of the operation. 否則，作業的結果會是 falseOtherwise, the result of the operation is false.
• x || y 的運算會評估為 x ? true : yThe operation x || y is evaluated as x ? true : y. 換句話說，x 會先進行評估，並轉換成類型 boolIn other words, x is first evaluated and converted to type bool. 然後，如果 truex，則會 true作業的結果。Then, if x is true, the result of the operation is true. 否則，y 會進行評估並轉換成類型 bool，而這會成為作業的結果。Otherwise, y is evaluated and converted to type bool, and this becomes the result of the operation.

### 使用者定義條件式邏輯運算子User-defined conditional logical operators

&&|| 的運算元屬於宣告適用的使用者定義 operator &operator |的類型時，下列兩項都必須為 true，其中 T 是所選取之運算子的宣告類型：When the operands of && or || are of types that declare an applicable user-defined operator & or operator |, both of the following must be true, where T is the type in which the selected operator is declared:

• 傳回型別和所選運算子之每個參數的型別都必須 TThe return type and the type of each parameter of the selected operator must be T. 換句話說，運算子必須計算 T類型之兩個運算元的邏輯 AND 或邏輯 OR，而且必須傳回 T類型的結果。In other words, the operator must compute the logical AND or the logical OR of two operands of type T, and must return a result of type T.
• T 必須包含 operator trueoperator false的宣告。T must contain declarations of operator true and operator false.

• 作業 x && y 會評估為 T.false(x) ? x : T.&(x, y)，其中 T.false(x) 是在 T中宣告之 operator false 的調用，而 T.&(x, y) 是所選 operator &的調用。The operation x && y is evaluated as T.false(x) ? x : T.&(x, y), where T.false(x) is an invocation of the operator false declared in T, and T.&(x, y) is an invocation of the selected operator &. 換句話說，x 會先進行評估，並在結果上叫用 operator false 以判斷 x 是否肯定為 false。In other words, x is first evaluated and operator false is invoked on the result to determine if x is definitely false. 然後，如果 x 肯定為 false，則作業的結果會是先前針對 x計算的值。Then, if x is definitely false, the result of the operation is the value previously computed for x. 否則，會評估 y，並在先前為 x 計算的值上叫用選取的 operator &，並針對 y 計算的值，以產生作業的結果。Otherwise, y is evaluated, and the selected operator & is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.
• 作業 x || y 會評估為 T.true(x) ? x : T.|(x, y)，其中 T.true(x) 是在 T中宣告之 operator true 的調用，而 T.|(x,y) 是所選 operator|的調用。The operation x || y is evaluated as T.true(x) ? x : T.|(x, y), where T.true(x) is an invocation of the operator true declared in T, and T.|(x,y) is an invocation of the selected operator|. 換句話說，x 會先進行評估，並在結果上叫用 operator true 以判斷 x 是否為絕對符合條件。In other words, x is first evaluated and operator true is invoked on the result to determine if x is definitely true. 然後，如果 x 肯定為 true，則作業的結果會是先前針對 x計算的值。Then, if x is definitely true, the result of the operation is the value previously computed for x. 否則，會評估 y，並在先前為 x 計算的值上叫用選取的 operator |，並針對 y 計算的值，以產生作業的結果。Otherwise, y is evaluated, and the selected operator | is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.

## Null 聯合運算子The null coalescing operator

?? 運算子稱為 null 聯合運算子。The ?? operator is called the null coalescing operator.

null_coalescing_expression
: conditional_or_expression
| conditional_or_expression '??' null_coalescing_expression
;


Null 聯合運算子是靠右關聯的，這表示作業會從右至左分組。The null coalescing operator is right-associative, meaning that operations are grouped from right to left. 例如，表單 a ?? b ?? c 的運算式會評估為 a ?? (b ?? c)For example, an expression of the form a ?? b ?? c is evaluated as a ?? (b ?? c). 一般來說，格式 E1 ?? E2 ?? ... ?? En 的運算式會傳回非 null 的第一個運算元，如果所有運算元都是 null，則傳回 null。In general terms, an expression of the form E1 ?? E2 ?? ... ?? En returns the first of the operands that is non-null, or null if all operands are null.

• 如果 A 存在，而且不是可為 null 的型別或參考型別，就會發生編譯時期錯誤。If A exists and is not a nullable type or a reference type, a compile-time error occurs.
• 如果 b 是動態運算式，則結果類型為 dynamicIf b is a dynamic expression, the result type is dynamic. 在執行時間，會先評估 aAt run-time, a is first evaluated. 如果 a 不是 null，a 會轉換為 dynamic，而這會變成結果。If a is not null, a is converted to dynamic, and this becomes the result. 否則，會評估 b，而這會變成結果。Otherwise, b is evaluated, and this becomes the result.
• 否則，如果 A 存在，而且是可為 null 的型別，且從 bA0都有隱含轉換，則結果型別會 A0Otherwise, if A exists and is a nullable type and an implicit conversion exists from b to A0, the result type is A0. 在執行時間，會先評估 aAt run-time, a is first evaluated. 如果 a 不是 null，a 會解除包裝為類型 A0，而這會變成結果。If a is not null, a is unwrapped to type A0, and this becomes the result. 否則，b 會進行評估並轉換成類型 A0，而這會變成結果。Otherwise, b is evaluated and converted to type A0, and this becomes the result.
• 否則，如果 A 存在，且從 bA的隱含轉換存在，則會 A結果類型。Otherwise, if A exists and an implicit conversion exists from b to A, the result type is A. 在執行時間，會先評估 aAt run-time, a is first evaluated. 如果 a 不是 null，a 就會變成結果。If a is not null, a becomes the result. 否則，b 會進行評估並轉換成類型 A，而這會變成結果。Otherwise, b is evaluated and converted to type A, and this becomes the result.
• 否則，如果 b 的類型 B，而從 aB的隱含轉換存在，則結果類型會是 BOtherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. 在執行時間，會先評估 aAt run-time, a is first evaluated. 如果 a 不是 null，a 會解除包裝為類型 A0 （如果 A 存在且可為 null）並轉換為類型 B，這會變成結果。If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. 否則，會評估 b 並成為結果。Otherwise, b is evaluated and becomes the result.
• 否則，ab 不相容，而且會發生編譯時期錯誤。Otherwise, a and b are incompatible, and a compile-time error occurs.

## 條件運算子Conditional operator

?: 運算子稱為「條件運算子」。The ?: operator is called the conditional operator. 有時候也稱為三元運算子。It is at times also called the ternary operator.

conditional_expression
: null_coalescing_expression
| null_coalescing_expression '?' expression ':' expression
;


?: 運算子的第一個運算元必須是可以隱含地轉換成 bool的運算式，或是實作為 operator true之型別的運算式。The first operand of the ?: operator must be an expression that can be implicitly converted to bool, or an expression of a type that implements operator true. 如果這兩項需求都不符合，就會發生編譯時期錯誤。If neither of these requirements is satisfied, a compile-time error occurs.

?: 運算子的第二個和第三個運算元，xy控制條件運算式的類型。The second and third operands, x and y, of the ?: operator control the type of the conditional expression.

• 如果 x 的類型為 X，而 y 的類型 Y 則為If x has type X and y has type Y then
• 如果隱含轉換（隱含轉換）從 XY（而不是從 YX）存在，則 Y 是條件運算式的類型。If an implicit conversion (Implicit conversions) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
• 如果隱含轉換（隱含轉換）從 YX（而不是從 XY）存在，則 X 是條件運算式的類型。If an implicit conversion (Implicit conversions) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
• 否則，就無法判斷運算式類型，且會發生編譯時期錯誤。Otherwise, no expression type can be determined, and a compile-time error occurs.
• 如果只有其中一個 xy 具有型別，而且 xy都可以隱含地轉換成該型別，則這就是條件運算式的型別。If only one of x and y has a type, and both x and y, of are implicitly convertible to that type, then that is the type of the conditional expression.
• 否則，就無法判斷運算式類型，且會發生編譯時期錯誤。Otherwise, no expression type can be determined, and a compile-time error occurs.

b ? x : y 格式之條件運算式的執行時間處理包含下列步驟：The run-time processing of a conditional expression of the form b ? x : y consists of the following steps:

• 首先會評估 b，並決定 bbool 值：First, b is evaluated, and the bool value of b is determined:
• 如果從 b 類型到 bool 的隱含轉換存在，則會執行此隱含轉換以產生 bool 值。If an implicit conversion from the type of b to bool exists, then this implicit conversion is performed to produce a bool value.
• 否則，會叫用 b 類型所定義的 operator true，以產生 bool 值。Otherwise, the operator true defined by the type of b is invoked to produce a bool value.
• 如果上述步驟所產生的 bool 值是 true的，則會評估 x，並將其轉換成條件運算式的類型，這會成為條件運算式的結果。If the bool value produced by the step above is true, then x is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression.
• 否則，會評估 y，並將其轉換成條件運算式的類型，這會成為條件運算式的結果。Otherwise, y is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression.

## 匿名函數運算式Anonymous function expressions

lambda_expression
: anonymous_function_signature '=>' anonymous_function_body
;

anonymous_method_expression
: 'delegate' explicit_anonymous_function_signature? block
;

anonymous_function_signature
: explicit_anonymous_function_signature
| implicit_anonymous_function_signature
;

explicit_anonymous_function_signature
: '(' explicit_anonymous_function_parameter_list? ')'
;

explicit_anonymous_function_parameter_list
: explicit_anonymous_function_parameter (',' explicit_anonymous_function_parameter)*
;

explicit_anonymous_function_parameter
: anonymous_function_parameter_modifier? type identifier
;

anonymous_function_parameter_modifier
: 'ref'
| 'out'
;

implicit_anonymous_function_signature
: '(' implicit_anonymous_function_parameter_list? ')'
| implicit_anonymous_function_parameter
;

implicit_anonymous_function_parameter_list
: implicit_anonymous_function_parameter (',' implicit_anonymous_function_parameter)*
;

implicit_anonymous_function_parameter
: identifier
;

anonymous_function_body
: expression
| block
;


=> 運算子與指派（=）具有相同的優先順序，而且為右向關聯。The => operator has the same precedence as assignment (=) and is right-associative.

lambda_expression形式的匿名函式的參數可以明確或隱含類型。The parameters of an anonymous function in the form of a lambda_expression can be explicitly or implicitly typed. 在明確類型的參數清單中，會明確陳述每個參數的類型。In an explicitly typed parameter list, the type of each parameter is explicitly stated. 在隱含型別參數清單中，參數的型別是從匿名函式發生的內容推斷而來，特別是當匿名函式轉換成相容的委派型別或運算式樹狀架構型別時，該型別會提供參數類型（匿名函數轉換）。In an implicitly typed parameter list, the types of the parameters are inferred from the context in which the anonymous function occurs—specifically, when the anonymous function is converted to a compatible delegate type or expression tree type, that type provides the parameter types (Anonymous function conversions).

( param ) => expr


param => expr


x => x + 1                              // Implicitly typed, expression body
x => { return x + 1; }                  // Implicitly typed, statement body
(int x) => x + 1                        // Explicitly typed, expression body
(int x) => { return x + 1; }            // Explicitly typed, statement body
(x, y) => x * y                         // Multiple parameters
() => Console.WriteLine()               // No parameters
async (t1,t2) => await t1 + await t2    // Async
delegate (int x) { return x + 1; }      // Anonymous method expression
delegate { return 1 + 1; }              // Parameter list omitted


• anonymous_method_expression允許完全省略參數清單，產生可轉換性以委派任何值參數清單的類型。anonymous_method_expressions permit the parameter list to be omitted entirely, yielding convertibility to delegate types of any list of value parameters.
• lambda_expression允許省略和推斷參數類型，而anonymous_method_expressions 需要明確陳述參數類型。lambda_expressions permit parameter types to be omitted and inferred whereas anonymous_method_expressions require parameter types to be explicitly stated.
• Lambda_expression的主體可以是運算式或語句區塊，而anonymous_method_expression的主體必須是語句區塊。The body of a lambda_expression can be an expression or a statement block whereas the body of an anonymous_method_expression must be a statement block.
• 只有lambda_expression的會轉換成相容的運算式樹狀架構類型（運算式樹狀架構類型）。Only lambda_expressions have conversions to compatible expression tree types (Expression tree types).

### 匿名函數主體Anonymous function bodies

• 如果匿名函式包含簽章，則簽章中指定的參數可在本文中取得。If the anonymous function includes a signature, the parameters specified in the signature are available in the body. 如果匿名函式沒有簽章，它可以轉換成具有參數（匿名函式轉換）的委派類型或運算式類型，但無法在主體中存取參數。If the anonymous function has no signature it can be converted to a delegate type or expression type having parameters (Anonymous function conversions), but the parameters cannot be accessed in the body.
• 除了在最接近的封閉式匿名函式的簽章中指定的 refout 參數（如果有的話），這是主體存取 refout 參數的編譯時期錯誤。Except for ref or out parameters specified in the signature (if any) of the nearest enclosing anonymous function, it is a compile-time error for the body to access a ref or out parameter.
• this 的型別是結構型別時，本文就會發生編譯時期錯誤，thisWhen the type of this is a struct type, it is a compile-time error for the body to access this. 無論存取是明確的（如 this.x）還是隱含的（如 x，其中 x 是結構的實例成員）都是如此。This is true whether the access is explicit (as in this.x) or implicit (as in x where x is an instance member of the struct). 此規則只會禁止這類存取，而且不會影響成員查閱結果是否在結構的成員中。This rule simply prohibits such access and does not affect whether member lookup results in a member of the struct.
• 主體可以存取匿名函數的外部變數（外部變數）。The body has access to the outer variables (Outer variables) of the anonymous function. 外部變數的存取將會參考在評估lambda_expressionanonymous_method_expression時（匿名函數運算式的評估）所使用的變數實例。Access of an outer variable will reference the instance of the variable that is active at the time the lambda_expression or anonymous_method_expression is evaluated (Evaluation of anonymous function expressions).
• 本文所包含的 goto 語句、break 語句或 continue 語句，其目標是在主體之外，或包含在內含匿名函式的主體內，這是一個編譯時期錯誤。It is a compile-time error for the body to contain a goto statement, break statement, or continue statement whose target is outside the body or within the body of a contained anonymous function.
• 主體中的 return 語句會從最接近的封閉式匿名函式（而不是從封入函式成員）的調用中傳回控制權。A return statement in the body returns control from an invocation of the nearest enclosing anonymous function, not from the enclosing function member. return 語句中指定的運算式必須隱含地轉換為最接近的封入lambda_expressionanonymous_method_expression轉換的委派類型或運算式樹狀架構類型的傳回類型（匿名函數轉換）。An expression specified in a return statement must be implicitly convertible to the return type of the delegate type or expression tree type to which the nearest enclosing lambda_expression or anonymous_method_expression is converted (Anonymous function conversions).

### 多載解析和匿名函式Overload resolution and anonymous functions

class ItemList<T>: List<T>
{
public int Sum(Func<T,int> selector) {
int sum = 0;
foreach (T item in this) sum += selector(item);
return sum;
}

public double Sum(Func<T,double> selector) {
double sum = 0;
foreach (T item in this) sum += selector(item);
return sum;
}
}


ItemList<T> 類別有兩個 Sum 方法。The ItemList<T> class has two Sum methods. 每個都會接受一個 selector 引數，這會將值從清單專案中解壓縮到總和。Each takes a selector argument, which extracts the value to sum over from a list item. 已解壓縮的值可以是 intdouble，而產生的總和同樣也是 intdoubleThe extracted value can be either an int or a double and the resulting sum is likewise either an int or a double.

class Detail
{
public int UnitCount;
public double UnitPrice;
...
}

void ComputeSums() {
ItemList<Detail> orderDetails = GetOrderDetails(...);
int totalUnits = orderDetails.Sum(d => d.UnitCount);
double orderTotal = orderDetails.Sum(d => d.UnitPrice * d.UnitCount);
...
}


orderDetails.Sum的第一個調用中，這兩個 Sum 方法都適用，因為匿名函數 d => d. UnitCountFunc<Detail,int>Func<Detail,double>相容。In the first invocation of orderDetails.Sum, both Sum methods are applicable because the anonymous function d => d. UnitCount is compatible with both Func<Detail,int> and Func<Detail,double>. 不過，多載解析會挑選第一個 Sum 方法，因為轉換成 Func<Detail,int> 比轉換成 Func<Detail,double>的效果更好。However, overload resolution picks the first Sum method because the conversion to Func<Detail,int> is better than the conversion to Func<Detail,double>.

orderDetails.Sum的第二個調用中，只有第二個 Sum 方法是適用的，因為匿名函數 d => d.UnitPrice * d.UnitCount 會產生 double類型的值。In the second invocation of orderDetails.Sum, only the second Sum method is applicable because the anonymous function d => d.UnitPrice * d.UnitCount produces a value of type double. 因此，多載解析會挑選該調用的第二個 Sum 方法。Thus, overload resolution picks the second Sum method for that invocation.

### 外部變數Outer variables

#### 已捕捉的外部變數Captured outer variables

using System;

delegate int D();

class Test
{
static D F() {
int x = 0;
D result = () => ++x;
return result;
}

static void Main() {
D d = F();
Console.WriteLine(d());
Console.WriteLine(d());
Console.WriteLine(d());
}
}


1
2
3


#### 區域變數的具現化Instantiation of local variables

static void F() {
for (int i = 0; i < 3; i++) {
int x = i * 2 + 1;
...
}
}


static void F() {
int x;
for (int i = 0; i < 3; i++) {
x = i * 2 + 1;
...
}
}


using System;

delegate void D();

class Test
{
static D[] F() {
D[] result = new D[3];
for (int i = 0; i < 3; i++) {
int x = i * 2 + 1;
result[i] = () => { Console.WriteLine(x); };
}
return result;
}

static void Main() {
foreach (D d in F()) d();
}
}


1
3
5


static D[] F() {
D[] result = new D[3];
int x;
for (int i = 0; i < 3; i++) {
x = i * 2 + 1;
result[i] = () => { Console.WriteLine(x); };
}
return result;
}


5
5
5


static D[] F() {
D[] result = new D[3];
for (int i = 0; i < 3; i++) {
result[i] = () => { Console.WriteLine(i); };
}
return result;
}


3
3
3


static D[] F() {
D[] result = new D[3];
int x = 0;
for (int i = 0; i < 3; i++) {
int y = 0;
result[i] = () => { Console.WriteLine("{0} {1}", ++x, ++y); };
}
return result;
}


1 1
2 1
3 1


using System;

delegate void Setter(int value);

delegate int Getter();

class Test
{
static void Main() {
int x = 0;
Setter s = (int value) => { x = value; };
Getter g = () => { return x; };
s(5);
Console.WriteLine(g());
s(10);
Console.WriteLine(g());
}
}


5
10


## 查詢運算式Query expressions

query_expression
: from_clause query_body
;

from_clause
: 'from' type? identifier 'in' expression
;

query_body
: query_body_clauses? select_or_group_clause query_continuation?
;

query_body_clauses
: query_body_clause
| query_body_clauses query_body_clause
;

query_body_clause
: from_clause
| let_clause
| where_clause
| join_clause
| join_into_clause
| orderby_clause
;

let_clause
: 'let' identifier '=' expression
;

where_clause
: 'where' boolean_expression
;

join_clause
: 'join' type? identifier 'in' expression 'on' expression 'equals' expression
;

join_into_clause
: 'join' type? identifier 'in' expression 'on' expression 'equals' expression 'into' identifier
;

orderby_clause
: 'orderby' orderings
;

orderings
: ordering (',' ordering)*
;

ordering
: expression ordering_direction?
;

ordering_direction
: 'ascending'
| 'descending'
;

select_or_group_clause
: select_clause
| group_clause
;

select_clause
: 'select' expression
;

group_clause
: 'group' expression 'by' expression
;

query_continuation
: 'into' identifier query_body
;


### 查詢運算式轉譯Query expression translation

#### 具有接續的 Select 和 groupby 子句Select and groupby clauses with continuations

from ... into x ...


from x in ( from ... ) ...


from c in customers
group c by c.Country into g
select new { Country = g.Key, CustCount = g.Count() }


from g in
from c in customers
group c by c.Country
select new { Country = g.Key, CustCount = g.Count() }


customers.
GroupBy(c => c.Country).
Select(g => new { Country = g.Key, CustCount = g.Count() })


#### 明確範圍變數類型Explicit range variable types

from T x in e


from x in ( e ) . Cast < T > ( )


join T x in e on k1 equals k2


join x in ( e ) . Cast < T > ( ) on k1 equals k2


from Customer c in customers
where c.City == "London"
select c


from c in customers.Cast<Customer>()
where c.City == "London"
select c


customers.
Cast<Customer>().
Where(c => c.City == "London")


#### 退化查詢運算式Degenerate query expressions

from x in e select x


( e ) . Select ( x => x )


from c in customers
select c


customers.Select(c => c)


「退化查詢運算式」（完整）會選取來源的元素。A degenerate query expression is one that trivially selects the elements of the source. 翻譯的較新階段會移除其他轉譯步驟引進的退化查詢，方法是將它們取代為其來源。A later phase of the translation removes degenerate queries introduced by other translation steps by replacing them with their source. 不過，請務必確保查詢運算式的結果永遠不是來源物件本身，因為這會向查詢的用戶端顯示來源的類型和識別。It is important however to ensure that the result of a query expression is never the source object itself, as that would reveal the type and identity of the source to the client of the query. 因此，此步驟會藉由明確地在來源上呼叫 Select，來保護直接寫入原始程式碼的退化查詢。Therefore this step protects degenerate queries written directly in source code by explicitly calling Select on the source. 然後，由 Select 和其他查詢運算子的實作者負責，以確保這些方法永遠不會傳回來源物件本身。It is then up to the implementers of Select and other query operators to ensure that these methods never return the source object itself.

#### From、let、where、join 和 orderby 子句From, let, where, join and orderby clauses

from x1 in e1
from x2 in e2
select v


( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => v )


from x1 in e1
from x2 in e2
...


from * in ( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => new { x1 , x2 } )
...


from x in e
let y = f
...


from * in ( e ) . Select ( x => new { x , y = f } )
...


from x in e
where f
...


from x in ( e ) . Where ( x => f )
...


from x1 in e1
join x2 in e2 on k1 equals k2
select v


( e1 ) . Join( e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => v )


from x1 in e1
join x2 in e2 on k1 equals k2
...


from * in ( e1 ) . Join( e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => new { x1 , x2 })
...


from x1 in e1
join x2 in e2 on k1 equals k2 into g
select v


( e1 ) . GroupJoin( e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => v )


from x1 in e1
join x2 in e2 on k1 equals k2 into g
...


from * in ( e1 ) . GroupJoin( e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => new { x1 , g })
...


from x in e
orderby k1 , k2 , ..., kn
...


from x in ( e ) .
OrderBy ( x => k1 ) .
ThenBy ( x => k2 ) .
... .
ThenBy ( x => kn )
...


from c in customers
from o in c.Orders
select new { c.Name, o.OrderID, o.Total }


customers.
SelectMany(c => c.Orders,
(c,o) => new { c.Name, o.OrderID, o.Total }
)


from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }


from * in customers.
SelectMany(c => c.Orders, (c,o) => new { c, o })
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }


customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(x => x.o.Total).
Select(x => new { x.c.Name, x.o.OrderID, x.o.Total })


from o in orders
let t = o.Details.Sum(d => d.UnitPrice * d.Quantity)
where t >= 1000
select new { o.OrderID, Total = t }


from * in orders.
Select(o => new { o, t = o.Details.Sum(d => d.UnitPrice * d.Quantity) })
where t >= 1000
select new { o.OrderID, Total = t }


orders.
Select(o => new { o, t = o.Details.Sum(d => d.UnitPrice * d.Quantity) }).
Where(x => x.t >= 1000).
Select(x => new { x.o.OrderID, Total = x.t })


from c in customers
join o in orders on c.CustomerID equals o.CustomerID
select new { c.Name, o.OrderDate, o.Total }


customers.Join(orders, c => c.CustomerID, o => o.CustomerID,
(c, o) => new { c.Name, o.OrderDate, o.Total })


from c in customers
join o in orders on c.CustomerID equals o.CustomerID into co
let n = co.Count()
where n >= 10
select new { c.Name, OrderCount = n }


from * in customers.
GroupJoin(orders, c => c.CustomerID, o => o.CustomerID,
(c, co) => new { c, co })
let n = co.Count()
where n >= 10
select new { c.Name, OrderCount = n }


customers.
GroupJoin(orders, c => c.CustomerID, o => o.CustomerID,
(c, co) => new { c, co }).
Select(x => new { x, n = x.co.Count() }).
Where(y => y.n >= 10).
Select(y => new { y.x.c.Name, OrderCount = y.n)


from o in orders
orderby o.Customer.Name, o.Total descending
select o


orders.
OrderBy(o => o.Customer.Name).
ThenByDescending(o => o.Total)


#### 選取子句Select clauses

from x in e select v


( e ) . Select ( x => v )


( e )


from c in customers.Where(c => c.City == "London")
select c


customers.Where(c => c.City == "London")


#### Groupby 子句Groupby clauses

from x in e group v by k


( e ) . GroupBy ( x => k , x => v )


( e ) . GroupBy ( x => k )


from c in customers
group c.Name by c.Country


customers.
GroupBy(c => c.Country, c => c.Name)


#### 透明識別碼Transparent identifiers

• 當透明識別碼當做匿名函式中的參數出現時，相關聯匿名型別的成員會自動在匿名函式主體的範圍內。When a transparent identifier occurs as a parameter in an anonymous function, the members of the associated anonymous type are automatically in scope in the body of the anonymous function.
• 當具有透明識別碼的成員在範圍內時，該成員的成員也會在範圍中。When a member with a transparent identifier is in scope, the members of that member are in scope as well.
• 當透明識別碼當做匿名物件初始化運算式中的成員宣告子出現時，它會引進具有透明識別碼的成員。When a transparent identifier occurs as a member declarator in an anonymous object initializer, it introduces a member with a transparent identifier.
• 在上述的轉譯步驟中，透明識別碼一律會與匿名型別一起導入，並將多個範圍變數當做單一物件的成員來捕捉。In the translation steps described above, transparent identifiers are always introduced together with anonymous types, with the intent of capturing multiple range variables as members of a single object. 的執行C#允許使用與匿名型別不同的機制，將多個範圍變數群組在一起。An implementation of C# is permitted to use a different mechanism than anonymous types to group together multiple range variables. 下列轉譯範例假設使用匿名型別，並顯示如何將透明識別碼轉譯出來。The following translation examples assume that anonymous types are used, and show how transparent identifiers can be translated away.

from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.Total }


from * in customers.
SelectMany(c => c.Orders, (c,o) => new { c, o })
orderby o.Total descending
select new { c.Name, o.Total }


customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(* => o.Total).
Select(* => new { c.Name, o.Total })


customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(x => x.o.Total).
Select(x => new { x.c.Name, x.o.Total })


from c in customers
join o in orders on c.CustomerID equals o.CustomerID
join d in details on o.OrderID equals d.OrderID
join p in products on d.ProductID equals p.ProductID
select new { c.Name, o.OrderDate, p.ProductName }


from * in customers.
Join(orders, c => c.CustomerID, o => o.CustomerID,
(c, o) => new { c, o })
join d in details on o.OrderID equals d.OrderID
join p in products on d.ProductID equals p.ProductID
select new { c.Name, o.OrderDate, p.ProductName }


customers.
Join(orders, c => c.CustomerID, o => o.CustomerID, (c, o) => new { c, o }).
Join(details, * => o.OrderID, d => d.OrderID, (*, d) => new { *, d }).
Join(products, * => d.ProductID, p => p.ProductID, (*, p) => new { *, p }).
Select(* => new { c.Name, o.OrderDate, p.ProductName })


customers.
Join(orders, c => c.CustomerID, o => o.CustomerID,
(c, o) => new { c, o }).
Join(details, x => x.o.OrderID, d => d.OrderID,
(x, d) => new { x, d }).
Join(products, y => y.d.ProductID, p => p.ProductID,
(y, p) => new { y, p }).
Select(z => new { z.y.x.c.Name, z.y.x.o.OrderDate, z.p.ProductName })


### 查詢運算式模式The query expression pattern

delegate R Func<T1,R>(T1 arg1);

delegate R Func<T1,T2,R>(T1 arg1, T2 arg2);

class C
{
public C<T> Cast<T>();
}

class C<T> : C
{
public C<T> Where(Func<T,bool> predicate);

public C<U> Select<U>(Func<T,U> selector);

public C<V> SelectMany<U,V>(Func<T,C<U>> selector,
Func<T,U,V> resultSelector);

public C<V> Join<U,K,V>(C<U> inner, Func<T,K> outerKeySelector,
Func<U,K> innerKeySelector, Func<T,U,V> resultSelector);

public C<V> GroupJoin<U,K,V>(C<U> inner, Func<T,K> outerKeySelector,
Func<U,K> innerKeySelector, Func<T,C<U>,V> resultSelector);

public O<T> OrderBy<K>(Func<T,K> keySelector);

public O<T> OrderByDescending<K>(Func<T,K> keySelector);

public C<G<K,T>> GroupBy<K>(Func<T,K> keySelector);

public C<G<K,E>> GroupBy<K,E>(Func<T,K> keySelector,
Func<T,E> elementSelector);
}

class O<T> : C<T>
{
public O<T> ThenBy<K>(Func<T,K> keySelector);

public O<T> ThenByDescending<K>(Func<T,K> keySelector);
}

class G<K,T> : C<T>
{
public K Key { get; }
}


System.Linq 命名空間會針對任何實作為 System.Collections.Generic.IEnumerable<T> 介面的型別，提供查詢運算子模式的執行。The System.Linq namespace provides an implementation of the query operator pattern for any type that implements the System.Collections.Generic.IEnumerable<T> interface.

## 指派運算子Assignment operators

assignment
: unary_expression assignment_operator expression
;

assignment_operator
: '='
| '+='
| '-='
| '*='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| right_shift_assignment
;


= 運算子稱為「簡單指派運算子」。The = operator is called the simple assignment operator. 它會將右運算元的值指派給左運算元所指定的變數、屬性或索引子元素。It assigns the value of the right operand to the variable, property, or indexer element given by the left operand. 簡單指派運算子的左運算元可能不是事件存取權（除非如類似欄位的事件中所述）。The left operand of the simple assignment operator may not be an event access (except as described in Field-like events). 簡單指派運算子會在簡單指派中說明。The simple assignment operator is described in Simple assignment.

= 運算子以外的指派運算子稱為複合指派運算子The assignment operators other than the = operator are called the compound assignment operators. 這些運算子會對兩個運算元執行指示的作業，然後將產生的值指派給左運算元所指定的變數、屬性或索引子元素。These operators perform the indicated operation on the two operands, and then assign the resulting value to the variable, property, or indexer element given by the left operand. 複合指派中會描述複合指派運算子。The compound assignment operators are described in Compound assignment.

### 單一指派Simple assignment

= 運算子稱為「簡單指派運算子」。The = operator is called the simple assignment operator.

x = y 表單的簡單指派的執行時間處理是由下列步驟所組成：The run-time processing of a simple assignment of the form x = y consists of the following steps:

• 如果 x 分類為變數：If x is classified as a variable:
• 評估 x 以產生變數。x is evaluated to produce the variable.
• 系統會評估 y，並在必要時，透過隱含轉換（隱含轉換）轉換成 x 的類型。y is evaluated and, if required, converted to the type of x through an implicit conversion (Implicit conversions).
• 如果 x 所指定的變數是reference_type的陣列元素，則會執行執行時間檢查，以確保為 y 計算的值與 x 為元素的陣列實例相容。If the variable given by x is an array element of a reference_type, a run-time check is performed to ensure that the value computed for y is compatible with the array instance of which x is an element. 如果 ynull，或是隱含的參考轉換（隱含的參考轉換）是從所 y 參考之實例的實際型別（包含 x的陣列實例的實際元素型別）存在，則檢查成功。The check succeeds if y is null, or if an implicit reference conversion (Implicit reference conversions) exists from the actual type of the instance referenced by y to the actual element type of the array instance containing x. 否則會擲回 System.ArrayTypeMismatchExceptionOtherwise, a System.ArrayTypeMismatchException is thrown.
• 評估和轉換 y 所產生的值會儲存在評估 x所指定的位置。The value resulting from the evaluation and conversion of y is stored into the location given by the evaluation of x.
• 如果 x 分類為屬性或索引子存取：If x is classified as a property or indexer access:
• 實例運算式（如果 x 不是 static），而且會評估與 x 相關聯的引數清單（如果 x 是索引子存取），而結果會用於後續的 set 存取子調用中。The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent set accessor invocation.
• 系統會評估 y，並在必要時，透過隱含轉換（隱含轉換）轉換成 x 的類型。y is evaluated and, if required, converted to the type of x through an implicit conversion (Implicit conversions).
• xset 存取子會使用針對 y 計算的值做為其 value 引數來叫用。The set accessor of x is invoked with the value computed for y as its value argument.

string[] sa = new string[10];
object[] oa = sa;

oa[0] = null;               // Ok
oa[1] = "Hello";            // Ok
oa[2] = new ArrayList();    // ArrayTypeMismatchException


struct_type中宣告的屬性或索引子是指派的目標時，與屬性或索引子存取相關聯的實例運算式必須分類為變數。When a property or indexer declared in a struct_type is the target of an assignment, the instance expression associated with the property or indexer access must be classified as a variable. 如果實例運算式分類為值，則會發生系結時錯誤。If the instance expression is classified as a value, a binding-time error occurs. 因為有成員存取權，所以相同的規則也適用于欄位。Because of Member access, the same rule also applies to fields.

struct Point
{
int x, y;

public Point(int x, int y) {
this.x = x;
this.y = y;
}

public int X {
get { return x; }
set { x = value; }
}

public int Y {
get { return y; }
set { y = value; }
}
}

struct Rectangle
{
Point a, b;

public Rectangle(Point a, Point b) {
this.a = a;
this.b = b;
}

public Point A {
get { return a; }
set { a = value; }
}

public Point B {
get { return b; }
set { b = value; }
}
}


Point p = new Point();
p.X = 100;
p.Y = 100;
Rectangle r = new Rectangle();
r.A = new Point(10, 10);
r.B = p;


Rectangle r = new Rectangle();
r.A.X = 10;
r.A.Y = 10;
r.B.X = 100;
r.B.Y = 100;


### 複合指派Compound assignment

x op= y 格式的作業會藉由套用二元運算子多載解析（二元運算子多載解析）來處理，就如同 x op y寫入作業一樣。An operation of the form x op= y is processed by applying binary operator overload resolution (Binary operator overload resolution) as if the operation was written x op y. 如此一來，Then,

• 如果選取之運算子的傳回型別可以隱含地轉換成 x的型別，則會將作業評估為 x = x op y，但只會評估 x 一次。If the return type of the selected operator is implicitly convertible to the type of x, the operation is evaluated as x = x op y, except that x is evaluated only once.
• 否則，如果選取的運算子是預先定義的運算子，而且選取之運算子的傳回類型明確地轉換成 x的類型，而且如果 y 可以隱含地轉換成 x 的類型，或運算子是移位運算子，則會將運算評估為 x = (T)(x op y)，其中 T 只會評估一次。Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x, and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y), where T is the type of x, except that x is evaluated only once.
• 否則，複合指派會無效，而且會發生系結時錯誤。Otherwise, the compound assignment is invalid, and a binding-time error occurs.

「僅評估一次」一詞表示在評估 x op y時，x 的任何組成運算式的結果都會暫時儲存，然後在執行指派給 x時重複使用。The term "evaluated only once" means that in the evaluation of x op y, the results of any constituent expressions of x are temporarily saved and then reused when performing the assignment to x. 例如，在指派 A()[B()] += C()中，其中 A 是傳回 int[]的方法，而 BC 是傳回 int的方法，則只會叫用一次方法，順序 ABCFor example, in the assignment A()[B()] += C(), where A is a method returning int[], and B and C are methods returning int, the methods are invoked only once, in the order A, B, C.

byte b = 0;
char ch = '\0';
int i = 0;

b += 1;             // Ok
b += 1000;          // Error, b = 1000 not permitted
b += i;             // Error, b = i not permitted
b += (byte)i;       // Ok

ch += 1;            // Error, ch = 1 not permitted
ch += (char)1;      // Ok


int? i = 0;
i += 1;             // Ok


### 事件指派Event assignment

• 會評估事件存取的實例運算式（如果有的話）。The instance expression, if any, of the event access is evaluated.
• 系統會評估 +=-= 運算子的右運算元，並在必要時，透過隱含轉換（隱含轉換）轉換為左運算元的類型。The right operand of the += or -= operator is evaluated, and, if required, converted to the type of the left operand through an implicit conversion (Implicit conversions).
• 系統會叫用事件的事件存取子，其中包含由右運算元組成的引數清單、在評估之後，以及必要的轉換。An event accessor of the event is invoked, with argument list consisting of the right operand, after evaluation and, if necessary, conversion. 如果 +=運算子，則會叫用 add 存取子;如果 -=運算子，則會叫用 remove 存取子。If the operator was +=, the add accessor is invoked; if the operator was -=, the remove accessor is invoked.

## 運算式Expression

expression
: non_assignment_expression
| assignment
;

non_assignment_expression
: conditional_expression
| lambda_expression
| query_expression
;


## 常數運算式Constant expressions

Constant_expression是可以在編譯時期完整評估的運算式。A constant_expression is an expression that can be fully evaluated at compile-time.

constant_expression
: expression
;


• 常值（包括 null 常值）。Literals (including the null literal).
• 類別和結構類型 const 成員的參考。References to const members of class and struct types.
• 列舉類型之成員的參考。References to members of enumeration types.
• const 參數或區域變數的參考References to const parameters or local variables
• 以括弧括住的子運算式，本身就是常數運算式。Parenthesized sub-expressions, which are themselves constant expressions.
• Cast 運算式，前提是目標型別是上列其中一種類型。Cast expressions, provided the target type is one of the types listed above.
• checkedunchecked 運算式checked and unchecked expressions
• 預設值運算式Default value expressions
• Nameof 運算式Nameof expressions
• 預先定義的 +-!~ 一元運算子。The predefined +, -, !, and ~ unary operators.
• 預先定義的 +-*/%<<>>&|^&&||==!=<><=>= 二元運算子，前提是每個運算元都是上列的類型。The predefined +, -, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, and >= binary operators, provided each operand is of a type listed above.
• ?: 條件運算子。The ?: conditional operator.

• 身分識別轉換Identity conversions
• 數值轉換Numeric conversions
• 列舉轉換Enumeration conversions
• 常數運算式轉換Constant expression conversions
• 隱含和明確的參考轉換，前提是轉換的來源是會評估為 null 值的常數運算式。Implicit and explicit reference conversions, provided that the source of the conversions is a constant expression that evaluates to the null value.

class C {
const object i = 5;         // error: boxing conversion not permitted
const object str = "hello"; // error: implicit reference conversion
}


i 的初始化是錯誤的，因為需要進行裝箱轉換。the initialization of i is an error because a boxing conversion is required. Str 的初始化是錯誤，因為需要非 null 值的隱含參考轉換。The initialization of str is an error because an implicit reference conversion from a non-null value is required.

## 布林運算式Boolean expressions

Boolean_expression是產生類型 bool結果的運算式;直接或透過應用程式的 operator true，如下所指定的特定內容。A boolean_expression is an expression that yields a result of type bool; either directly or through application of operator true in certain contexts as specified in the following.

boolean_expression
: expression
;


If_statementif 語句）、 while_statementwhile 語句）、 do_statementdo 語句）或for_statementfor 語句）的控制條件運算式是boolean_expressionThe controlling conditional expression of an if_statement (The if statement), while_statement (The while statement), do_statement (The do statement), or for_statement (The for statement) is a boolean_expression. ?: 運算子（條件運算子）的控制條件運算式會遵循與boolean_expression相同的規則，但會將運算子優先順序的原因分類為conditional_or_expressionThe controlling conditional expression of the ?: operator (Conditional operator) follows the same rules as a boolean_expression, but for reasons of operator precedence is classified as a conditional_or_expression.

• 如果 E 可以隱含地轉換成 bool 則在執行時間會套用隱含轉換。If E is implicitly convertible to bool then at runtime that implicit conversion is applied.
• 否則，會使用一元運算子多載解析（一元運算子多載解析）來尋找 E上運算子 true 的唯一最佳執行，而該實作為在執行時間套用。Otherwise, unary operator overload resolution (Unary operator overload resolution) is used to find a unique best implementation of operator true on E, and that implementation is applied at runtime.
• 如果找不到這類運算子，則會發生系結時錯誤。If no such operator is found, a binding-time error occurs.