# 表达式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.
• 空文本。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. 归类为 nothing 的表达式仅在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. 只存在一个三元运算符 ?:;它采用三个操作数，并使用中缀表示法（c ? x : y）。Only one ternary operator, ?:, exists; it takes three operands and uses infix notation (c ? x : y).

### 运算符优先级和关联性Operator precedence and associativity

SectionSection 类别Category 运算符Operators

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 是一个可重载的一元运算符），并且 xX类型的表达式，则按以下方式处理：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:

• 确定操作 operator op(x,y) XY 提供的候选用户定义运算符集。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.
• 否则，两个操作数都将转换为 int类型。Otherwise, 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. 如果有一个或两个操作数为空（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. 如果两个操作数都非空，则提升运算符将对操作数进行解包，并应用基础运算符来生成 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 是类型参数，则该集是在每个指定为 object N T的主约束或辅助约束（类型参数约束）的每个类型中名为 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 的基类型中声明的非类型，并且与在 S 的基类型中声明的 M 类型参数相同的所有类型声明都将从集合中删除。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 的类型），如果 S 为除 object之外的类声明，则应用以下规则：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_type，则 T 的基类型是类类型 System.EnumSystem.ValueTypeobjectIf T is an enum_type, the base types of T are the class types System.Enum, System.ValueType, and object.
• 如果 Tstruct_type，则 T 的基类型是类类型 System.ValueTypeobjectIf T is a struct_type, the base types of T are the class types System.ValueType and object.
• 如果 Tclass_type，则 T 的基类型是 T的基类，包括类类型 objectIf T is a class_type, the base types of T are the base classes of T, including the class type object.
• 如果 Tinterface_type，则 T 的基类型是 T 和类类型 object的基接口。If T is an interface_type, the base types of T are the base interfaces of T and the class type object.
• 如果 Tarray_type，则 T 的基类型是类类型 System.ArrayobjectIf T is an array_type, the base types of T are the class types System.Array and object.
• 如果 Tdelegate_type，则 T 的基类型是类类型 System.DelegateobjectIf T is a delegate_type, the base types of T are the class types System.Delegate and object.

## 函数成员Function members

• 方法Methods
• 属性Properties
• EventsEvents
• 索引器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).
Property access P 调用包含类或结构中的属性 Pget 访问器。The get accessor of the property P in the containing class or struct is invoked. 如果 P 是只写的，则会发生编译时错误。A compile-time error occurs if P is write-only. 如果未 staticP，则 this实例表达式。If P is not static, the instance expression is this.
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 属性的 get 访问器。The get accessor of the property P in the class or struct T is invoked. 如果 PstaticP 是只写的，则会发生编译时错误。A compile-time error occurs if P is not static or if P is write-only.
T.P = value 类或结构 TP 属性的 set 访问器是通过参数列表 (value)调用的。The set accessor of the property P in the class or struct T is invoked with the argument list (value). 如果 PstaticP 为只读，则会发生编译时错误。A compile-time error occurs if P is not static or if P is read-only.
e.P e 类型指定的类、结构或接口中的属性 Pget 访问器在实例表达式 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 调用类或结构 TE 事件的 add 访问器。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 调用类或结构 TE 事件的 remove 访问器。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). 在将变量作为 output 参数传递的函数成员调用之后，变量被视为明确赋值（明确赋值）。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.

• 实例构造函数、方法、索引器和委托的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 是匿名函数，则显式参数类型推理显式参数类型推断）是从 EiTiIf 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

• 依赖于依赖）任何 Xj的所有未固定的类型 Xi 变量都是固定的（正在修复）。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输入类型输入类型）不存在，则将EiOutput type inferencesTi进行输出类型推理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.

#### 输出类型推断Output type inferences

• 如果 EU推断返回类型）且 T 为委托类型或具有返回类型 Tb的表达式树类型的匿名函数，则将ULower-bound inferencesTb进行下限推理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 的单个方法，则UU生成一个方法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.
• 否则，如果 EU类型的表达式，则将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为-1 的显式类型匿名函数，T 是具有参数类型 V1...Vk 的委托类型或表达式树类型，则对每个 Ui 进行精确推理（精确推断）从到对应的 0。UiViIf 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:

• VV1[...] 数组类型，U 是同一排名 U1[...] 的数组类型V is an array type V1[...] and U is an array type U1[...] of the same rank
• VV1? 类型，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:

• VV1[...] 数组类型，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[])

• VC<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>.

（"唯一性" 限制意味着在 case 接口 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
• 否则，如果 C<V1...Vk> V，则推理依赖于 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:

• UU1[...] 数组类型，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[]

• UU1? 类型，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>. 不从 U1X<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
• 否则，如果 C<U1...Uk> U，则推理依赖于 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

• 候选类型UjXi的边界集中的所有类型的集合开头。The set of candidate types Uj starts out as the set of all types in the set of bounds for Xi.
• 然后，我们依次检查每个绑定 for Xi：对于每个完全绑定 UXi Uj 的所有类型，这些类型与从候选集删除 U 不完全相同。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 中删除任何 Uj 类型的隐式转换。For 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 的每个上限 UUj 将从候选集删除没有隐式转换到 U 的所有类型。For 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 的主体是分类为 nothing （表达式分类）的表达式，或者是没有 return 语句的语句块包含表达式，则推断出的返回类型为 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 为 async 并且 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推断结果类型，则推断出的返回类型为 TIf 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);


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)


• 给定一组适用的候选函数成员后，该集合中的最佳函数成员就是。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中的每个自变量，参数的参数传递模式（即值、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
• 对于固定值参数或扩展创建的值参数，存在从自变量的类型到相应参数类型的隐式转换（隐式转换）或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 的转换优于从 ExQx的转换。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 数组，并且仅适用于其展开形式，则 MpMq更好。Otherwise, 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更具体的参数类型，则 MpMq更好。Otherwise, 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，并且存在从 ST 的标识转换E 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:
• ED 参数列表的上下文中存在的推断返回类型 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 具有返回类型 Y 或者 E 为 async 并且 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 的主体是一个完全匹配的表达式 YThe body of E is an expression that exactly matches Y
• E 的主体是一个语句块，其中每个 return 语句返回一个完全匹配的表达式 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
• T1 Task<S1>T2 Task<S2>S1 是比 S2 更好的转换目标T1 is Task<S1>, T2 is Task<S2>, and S1 is a better conversion target than S2
• T1 S1S1?，其中 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:
• S1sbyte 的，S2byteushortuintulongS1 is sbyte and S2 is byte, ushort, uint, or ulong
• S1short 并且 S2ushortuintulongS1 is short and S2 is ushort, uint, or ulong
• S1int 并且 S2uintulongS1 is int and S2 is uint, or ulong
• S1long 并且 S2ulongS1 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 视为类型 objectIf 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. 如果 nullE 的值，则将引发 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. 此函数成员是通过应用规则来确定的，这些规则用于确定 E所引用的实例的运行时类型 M 的派生程度最高的实现（虚拟方法）。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

value_type中实现的函数成员可在以下情况下通过value_type的装箱实例进行调用：A function member implemented in a value_type can be invoked through a boxed instance of that value_type in the following situations:

• 当函数成员是从类型 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. 内插字符串表达式是已分解为单独标记的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后跟 $ 符号，则格式字符串文本就是该标记。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.
• 否则，如果 T 中的 I 的成员查找（成员查找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 的命名空间声明括起来，并且命名空间声明包含将名称 I 与命名空间或类型相关联的extern_alias_directiveusing_alias_directive ，则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 包含名称 IK 类型参数的可访问类型，则：Otherwise, if N contains an accessible type having name I and K type parameters, then:
• 如果 K 为零，且simple_name的位置由 N 的命名空间声明括起来，并且命名空间声明包含将名称 using_alias_directive 与命名空间或类型相关联的extern_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 为零，且命名空间声明包含将名称 I 与导入的命名空间或类型相关联的extern_alias_directiveusing_alias_directive ，则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_directives 命名空间声明导入的命名空间和类型声明包含一个名称 IK 类型参数的可访问类型或非扩展静态成员，则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_access包含primary_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. 下面的规则使用运行时类型（而不是primary_expression的编译时类型）在运行时应用member_access的含义。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.

• 如果 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 包含名称 IK 类型参数的可访问类型，则结果为使用给定类型参数构造的类型。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的类型，并且在 T 中包含 KI 的成员查找（成员查找）， 类型参数会生成匹配项，然后按如下所示对 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,
• 如果 E thisI 将标识一个自动实现的属性（自动实现的属性），而不使用 setter，并且引用出现在类或结构类型 T的实例构造函数中，则结果是一个变量，即 I 给定的 T 的实例中的 this所给定的自动属性的隐藏支持字段。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:
• 如果 nullE 的值，则将引发 System.NullReferenceExceptionIf the value of E is null, then a System.NullReferenceException is thrown.
• 否则，如果字段 readonly 并且引用出现在声明该字段的类的实例构造函数之外，则结果为值，即 E引用的对象中的字段的值 IOtherwise, 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指定的结构实例中的字段的值 IIf 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指定的结构实例中的字段 IOtherwise, 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;


### 调用表达式Invocation expressions

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


• Primary_expression具有 dynamic的编译时类型。The 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的方法或委托，则结果为 nothing。If the invocation_expression invokes a method or delegate that returns void, the result is nothing. 仅在statement_expressionexpression 语句）的上下文中或作为lambda_expression匿名函数表达式）的主体时，才允许将表达式归类为 nothing。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

• 构造方法调用的候选方法集。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_namemember_accessThe 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_namemember_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 是非泛型非泛型类Ci is a non-generic, non-nested class
• Mj 的名称是标识符The name of Mj is identifier
• 当作为如下所示的静态方法应用于参数时，Mj 是可访问和适用的Mj 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.
• 如果在给定的命名空间或编译单元中using_namespace_directives 导入的命名空间中 Ci 导入using_static_declarations并直接声明的类型 Mj，则这些扩展方法集是候选集。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.

C 用作目标，然后将方法调用处理为静态方法调用（对动态重载决策进行编译时检查）。Using C as a target, the method call is then processed as a static method invocation (Compile-time checking of dynamic overload resolution).

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_expressionA 是一个可选的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. 如果 nullD 的值，则将引发 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_access包含一个primary_no_array_creation_expression，后跟一个 "[" 标记，后跟一个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由一个或多个由逗号分隔的参数组成。The argument_list consists of one or more arguments, separated by commas.

element_access
: primary_no_array_creation_expression '[' expression_list ']'
;


• Primary_no_array_creation_expression具有 dynamic的编译时类型。The 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_expressionAargument_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 的隐式转换，因为从 shortint 的隐式转换和从 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. 如果 nullP 的值，则将引发 System.NullReferenceException，并且不执行任何其他步骤。If the value of P is null, a System.NullReferenceException is thrown and no further steps are executed.
• 根据 P引用的数组实例的每个维度的实际界限检查argument_list中每个表达式的值。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

• 构造由 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适用的函数成员），则从集中删除 IIf 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'
;


• 当在类的实例构造函数中的primary_expression中使用 this 时，它将分类为值。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.
• 当在类的实例方法或实例访问器中的primary_expression中使用 this 时，它将分类为值。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.
• 如果在结构的实例构造函数中的primary_expression中使用 this，则将其归类为变量。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.
• 如果在结构的实例方法或实例访问器中的primary_expression中使用 this，则将其归类为变量。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.
• 如果方法或访问器不是迭代器（迭代器），则 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:
• 实例表达式（如果 xstatic）和参数列表（如果 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.
• 使用运算符作为其 value 参数返回的值调用 xset 访问器。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.string类型中定义 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 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 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; } }
}


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兼容（委托声明），并且结果是对类型 D 的新创建委托的引用，该委托引用与 E相同的调用列表。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 是方法组，则将委托创建表达式作为方法组转换（方法组转换）作为 E D进行计算。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.
• 如果 nullE 的值，则将引发 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;
}
}


#### 匿名对象创建表达式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
: ','
;


• 将标记序列替换为type_name ，方法是将每个generic_dimension_specifier替换为具有相同的逗号数的type_argument_list ，并且关键字 object 每个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.

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.

• 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 * y 进行求值。the 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.

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_charactersAny 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

?+-!~++--、强制转换和 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_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 归类为 nothing，则会发生编译时错误。Otherwise, if E0 is classified as nothing a compile-time error occurs.

• 否则，让 T0 成为 E0的类型。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 的值类型，则 E 的类型 T0?，并且 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-conditional expressions as projection initializers

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


#### 空条件表达式作为语句表达式Null-conditional expressions as statement expressions

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，并 long结果的类型。If 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. Decimal 求反等效于使用 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:
• 实例表达式（如果 xstatic）和参数列表（如果 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.
• 使用运算符作为其 value 参数返回的值调用 xset 访问器。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 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_expressionparenthesized_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).

• 标记序列对于类型是正确的语法，而不是表达式的语法。The sequence of tokens is correct grammar for a type, but not for an expression.
• 标记序列对于类型是正确的语法，紧跟在右括号后面的标记是标记 "~"、标记 "!"、令牌 "("、标识符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的操作数称为任务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. 如果以下包含其中一项，则表达式 t 为可等待：An expression t is awaitable if one of the following holds:

• t 的编译时类型为 dynamict is of compile time type dynamic
• t 具有一个名为 GetAwaiter 的可访问实例或扩展方法，其中没有任何参数和类型参数，以及以下所有保留 A 的返回类型：t 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

• 通过 (t).GetAwaiter()计算表达式来获取 awaiter aAn awaiter a is obtained by evaluating the expression (t).GetAwaiter().
• 通过计算表达式 (a).IsCompleted获取 bool bA bool b is obtained by evaluating the expression (a).IsCompleted.
• 如果 false b，则评估将取决于 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.
• 紧随之后（如果 trueb），或在以后调用恢复委托（如果 b false），将计算表达式 (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. 否则，结果为 nothing。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 -0-0 +inf+inf -inf-inf NaNNaN
+x+x +z+z -z-z +0+0 -0-0 +inf+inf -inf-inf NaNNaN
-x-x -z-z +z+z -0-0 +0+0 -inf-inf +inf+inf NaNNaN
+0+0 +0+0 -0-0 +0+0 -0-0 NaNNaN NaNNaN NaNNaN
-0-0 -0-0 +0+0 -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 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 -0-0 +inf+inf -inf-inf NaNNaN
+x+x +z+z -z-z +inf+inf -inf-inf +0+0 -0-0 NaNNaN
-x-x -z-z +z+z -inf-inf +inf+inf -0-0 +0+0 NaNNaN
+0+0 +0+0 -0-0 NaNNaN NaNNaN +0+0 -0-0 NaNNaN
-0-0 -0-0 +0+0 NaNNaN NaNNaN -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 -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
-0-0 -0-0 -0-0 NaNNaN NaNNaN -0-0 -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);


Sum 根据 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 -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
-0-0 yy +0+0 -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);


二元 + 运算符的这些重载执行字符串串联。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 -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
-0-0 -y-y -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.

Decimal 等效于使用 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. 如果第二个操作数的列表与第一个操作数列表中连续条目的多个子列表匹配，则会删除最右侧匹配的子列表。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 为非负值，则设置为1）。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的低序位5位提供。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.

OperationOperation 结果Result
x == y true 如果 x 等于 yfalse，则为; 否则为。true if x is equal to y, false otherwise
x != y 如果 x 不等于 yfalse，则 true; 否则为。true if x is not equal to y, false otherwise
x < y 如果 x 小于 yfalse，则 true; 否则为。true if x is less than y, false otherwise
x > y 如果 x 大于 yfalse，则 true; 否则为。true if x is greater than y, false otherwise
x <= y 如果 x 小于或等于 yfalse，则 true; 否则为。true if x is less than or equal to y, false otherwise
x >= y 如果 x 大于或等于 yfalse，则 true; 否则为。true 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的所有运算符（!=除外） falseIf 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，则 falsex < y，但 !(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.
• 对于在每个字符位置都具有相同长度和相同字符的字符串实例，这两个值都是非空引用。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 的类型为引用类型，则 DE的实例引用的运行时类型。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 的值类型，则 DE的类型。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 是一个值类型，并且 D 存在从 T 到的装箱转换。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. 与强制转换表达式（强制转换表达式）不同，as 运算符永远不会引发异常。Unlike a cast expression (Cast expressions), the as operator never throws an exception. 相反，如果不可能指定的转换，则将 null结果值。Instead, 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. 此外，必须至少满足以下条件之一，否则将发生编译时错误：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 逻辑运算符Boolean logical operators

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


### 可以为 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 & y 还是 x | 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

• 运算 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. 然后，如果 truex，则计算 y，并将其转换为类型 bool，这就成为了运算结果。Then, if x is true, y is evaluated and converted to type bool, and this becomes the result of the operation. 否则，将 false操作的结果。Otherwise, 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

• 所选运算符的每个参数的返回类型和类型必须是 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 是否确实为 true。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 ?? b 表达式的类型取决于在操作数上可用的隐式转换。The type of the expression a ?? b depends on which implicit conversions are available on the operands. 按照优先顺序，a ?? b 的类型为 A0AB，其中 Aa 的类型（前提是 a 具有类型），Bb 的类型（前提是 b 有一个类型），A0A 的基础类型（如果 A 是可以为 null 的类型），或者 A 为。In order of preference, the type of a ?? b is A0, A, or B, where A is the type of a (provided that a has a type), B is the type of b (provided that b has a type), and A0 is the underlying type of A if A is a nullable type, or A otherwise. 具体而言，按如下所示处理 a ?? bSpecifically, a ?? b is processed as follows:

• 如果 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 转换为动态，这将成为结果。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存在隐式转换，则结果类型为 AOtherwise, 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
;


b ? x : y 首先计算 b的条件表达式。A conditional expression of the form b ? x : y first evaluates the condition b. 然后，如果 trueb，则将计算 x，并成为操作的结果。Then, if b is true, x is evaluated and becomes the result of the operation. 否则，将计算 y，并成为操作的结果。Otherwise, y is evaluated and becomes the result of the operation. 条件表达式从不同时计算 xyA conditional expression never evaluates both x and y.

?: 运算符的第一个操作数必须是可以隐式转换为 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 具有类型 YIf x has type X and y has type Y then
• 如果 X 中存在隐式转换（隐式转换）到 Y，但不是从 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.
• 如果 Y 中存在隐式转换（隐式转换）到 X，但不是从 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，并确定 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.

( param ) => expr


param => expr


Anonymous_method_expression格式的匿名函数的参数列表是可选的。The parameter list of an anonymous function in the form of an anonymous_method_expression is optional. 如果给定，则必须显式键入参数。If given, the parameters must be explicitly typed. 如果不是，则该匿名函数可转换为包含任何参数列表（不包含 out 参数）的委托。If not, the anonymous function is convertible to a delegate with any parameter list not containing out parameters.

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


Lambda_expressionanonymous_method_expressions 的行为是相同的，但以下情况除外：The behavior of lambda_expressions and anonymous_method_expressions is the same except for the following points:

• anonymous_method_expression允许完全省略参数列表，则可以 convertibility 委托任何值参数列表的类型。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_expression则需要显式声明参数类型。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_expressions 具有转换为兼容的表达式树类型（表达式树类型）。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 的类型为结构类型时，主体访问 this时会发生编译时错误。When 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);
...
}


### 外部变量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)


#### 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 子句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 归类为变量：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. 如果 y null，或者存在从 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:
• 实例表达式（如果 xstatic）和参数列表（如果 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 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的类型，则该运算将计算为 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)，其中 Tx的类型，但 x 只计算一次。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.

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 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 表达式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.