Expressions

式は一連の演算子とオペランドで構成されます。An expression is a sequence of operators and operands. この章では、構文、オペランドと演算子の評価順序、および式の意味を定義します。This chapter defines the syntax, order of evaluation of operands and operators, and meaning of expressions.

式の分類Expression classifications

式は、次のいずれかに分類されます。An expression is classified as one of the following:

  • 値です。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 演算子) のオペランドとして、または演算子 (is 演算子)、 as is または typeof 演算子 (typeof 演算子) としてのみ使用できます。An expression with this classification can only appear as the left hand side of a member_access (Member access), or as an operand for the as operator (The as operator), the is operator (The is operator), or the typeof operator (The typeof operator). その他のコンテキストでは、型として分類された式によってコンパイル時エラーが発生します。In any other context, an expression classified as a type causes a compile-time error.
  • メソッドグループ。メンバー参照 (メンバー参照) の結果として得られる一連のオーバーロードされたメソッドです。A method group, which is a set of overloaded methods resulting from a member lookup (Member lookup). メソッドグループには、関連付けられたインスタンス式と、関連する型引数リストを含めることができます。A method group may have an associated instance expression and an associated type argument list. インスタンスメソッドが呼び出されると、インスタンス式を評価した結果が this (このアクセス) によって表されるインスタンスになります。When an instance method is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access). メソッドグループは、 invocation_expression (呼び出し式)、 delegate_creation_expression (デリゲート作成式)、および is 演算子の左辺として許可され、互換性のあるデリゲート型 (メソッドグループ変換) に暗黙的に変換できます。A method group is permitted in an invocation_expression (Invocation expressions) , a delegate_creation_expression (Delegate creation expressions) and as the left hand side of an is operator, and can be implicitly converted to a compatible delegate type (Method group conversions). その他のコンテキストでは、メソッドグループとして分類された式によってコンパイル時エラーが発生します。In any other context, an expression classified as a method group causes a compile-time error.
  • Null リテラル。A null literal. この分類を持つ式は、参照型または null 許容型に暗黙的に変換できます。An expression with this classification can be implicitly converted to a reference type or nullable type.
  • 匿名関数。An anonymous function. この分類の式は、互換性のあるデリゲート型または式ツリー型に暗黙的に変換できます。An expression with this classification can be implicitly converted to a compatible delegate type or expression tree type.
  • プロパティアクセス。A property access. すべてのプロパティアクセスには、関連付けられた型、つまりプロパティの型があります。Every property access has an associated type, namely the type of the property. さらに、プロパティアクセスには、関連付けられたインスタンス式が含まれる場合があります。Furthermore, a property access may have an associated instance expression. get set インスタンスプロパティアクセスのアクセサー (またはブロック) が呼び出されると、インスタンス式を評価した結果が (このアクセス) によって表されるインスタンスになり 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. getインデクサーアクセスのアクセサー (または set ブロック) が呼び出されると、インスタンス式を評価した結果が (このアクセス) によって表されるインスタンスになり、 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。Nothing. このエラーは、式がの戻り値の型を持つメソッドの呼び出しである場合に発生し void ます。This occurs when the expression is an invocation of a method with a return type of void. Nothing として分類された式は、 statement_expression (式ステートメント) のコンテキストでのみ有効です。An expression classified as nothing is only valid in the context of a statement_expression (Expression statements).

式の最終的な結果は、名前空間、型、メソッドグループ、またはイベントアクセスにはなりません。The final result of an expression is never a namespace, type, method group, or event access. 前述のように、これらの式のカテゴリは、特定のコンテキストでのみ許可される中間構造です。Rather, as noted above, these categories of expressions are intermediate constructs that are only permitted in certain contexts.

プロパティアクセスまたはインデクサーアクセスは、 get アクセサー または set アクセサー の呼び出しを実行することによって、常に値として再分類されます。A property access or indexer access is always reclassified as a value by performing an invocation of the get accessor or the set accessor. 特定のアクセサーは、プロパティまたはインデクサーアクセスのコンテキストによって決定されます。アクセスが割り当てのターゲットである場合は、 set アクセサー が呼び出され、新しい値 (単純な割り当て) が割り当てられます。The particular accessor is determined by the context of the property or indexer access: If the access is the target of an assignment, the set accessor is invoked to assign a new value (Simple assignment). それ以外の場合は、 get アクセサー を呼び出して、現在の値 (式の値) を取得します。Otherwise, the get accessor is invoked to obtain the current value (Values of expressions).

式の値Values of expressions

式を含むほとんどのコンストラクトでは、最終的に を示す式が必要になります。Most of the constructs that involve an expression ultimately require the expression to denote a value. このような場合、実際の式が名前空間、型、メソッドグループ、または nothing を表していると、コンパイル時エラーが発生します。In such cases, if the actual expression denotes a namespace, a type, a method group, or nothing, a compile-time error occurs. ただし、式がプロパティアクセス、インデクサーアクセス、または変数を表している場合、プロパティ、インデクサー、または変数の値は暗黙的に置き換えられます。However, if the expression denotes a property access, an indexer access, or a variable, the value of the property, indexer, or variable is implicitly substituted:

  • 変数の値は、変数によって識別されるストレージの場所に現在格納されている値にすぎません。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

構成式 (引数、オペランド、レシーバー) の型または値に基づいて操作の意味を判断するプロセスは、多くの場合、 バインド と呼ばれます。The process of determining the meaning of an operation based on the type or value of constituent expressions (arguments, operands, receivers) is often referred to as binding. たとえば、メソッド呼び出しの意味は、受信側と引数の型に基づいて決定されます。For instance the meaning of a method call is determined based on the type of the receiver and arguments. 演算子の意味は、そのオペランドの型に基づいて決定されます。The meaning of an operator is determined based on the type of its operands.

C# では、通常、操作の意味はコンパイル時に決定され、その構成式のコンパイル時の型に基づいて決定されます。In C# the meaning of an operation is usually determined at compile-time, based on the compile-time type of its constituent expressions. 同様に、式にエラーが含まれている場合は、コンパイラによってエラーが検出され、報告されます。Likewise, if an expression contains an error, the error is detected and reported by the compiler. この方法は、 静的バインド と呼ばれます。This approach is known as static binding.

ただし、式が動的な式 (つまり、型を持つ) の場合、その式が参加しているすべてのバインディングは、 dynamic コンパイル時に存在する型ではなく、その実行時の型 (つまり、実行時に示されるオブジェクトの実際の型) に基づいている必要があることを示します。However, if an expression is a dynamic expression (i.e. has the type dynamic) this indicates that any binding that it participates in should be based on its run-time type (i.e. the actual type of the object it denotes at run-time) rather than the type it has at compile-time. そのため、このような操作のバインドは、プログラムの実行中に操作が実行される時間まで延期されます。The binding of such an operation is therefore deferred until the time where the operation is to be executed during the running of the program. これを 動的バインド と呼びます。This is referred to as dynamic binding.

操作が動的にバインドされる場合、コンパイラによるチェックはほとんどまたはまったく実行されません。When an operation is dynamically bound, little or no checking is performed by the compiler. 代わりに、実行時のバインドが失敗した場合、実行時にエラーが例外として報告されます。Instead if the run-time binding fails, errors are reported as exceptions at run-time.

C# での次の操作は、バインドの対象となります。The following operations in C# are subject to 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

動的な式が関係しない場合、C# では既定で静的バインドが使用されます。これは、構成式のコンパイル時の型が選択プロセスで使用されることを意味します。When no dynamic expressions are involved, C# defaults to static binding, which means that the compile-time types of constituent expressions are used in the selection process. ただし、上記の操作のいずれかの構成式が動的な式である場合、その操作は動的にバインドされます。However, when one of the constituent expressions in the operations listed above is a dynamic expression, the operation is instead dynamically bound.

バインド-時間Binding-time

静的バインドはコンパイル時に行われますが、動的バインドは実行時に行われます。Static binding takes place at compile-time, whereas dynamic binding takes place at run-time. 次のセクションでは、バインド 時間 とは、バインディングがいつ行われるかに応じて、コンパイル時または実行時を指します。In the following sections, the term binding-time refers to either compile-time or run-time, depending on when the binding takes place.

次の例は、静的バインディングと動的バインドの概念とバインド時の概念を示しています。The following example illustrates the notions of static and dynamic binding and of 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)

最初の2つの呼び出しは静的にバインドされます。のオーバーロードは、 Console.WriteLine 引数のコンパイル時の型に基づいて選択されます。The first two calls are statically bound: the overload of Console.WriteLine is picked based on the compile-time type of their argument. したがって、バインディング時間はコンパイル時です。Thus, the binding-time is compile-time.

3番目の呼び出しは動的にバインドされます。のオーバーロードは、 Console.WriteLine 引数の実行時の型に基づいて選択されます。The third call is dynamically bound: the overload of Console.WriteLine is picked based on the run-time type of its argument. これは、引数が動的な式である (コンパイル時の型がである) ために発生し dynamic ます。This happens because the argument is a dynamic expression -- its compile-time type is dynamic. そのため、3番目の呼び出しのバインディング時間は実行時です。Thus, the binding-time for the third call is run-time.

動的バインディングDynamic binding

動的バインドの目的は、C# プログラムが 動的オブジェクト(c# 型システムの通常の規則に従っていないオブジェクト) と対話できるようにすることです。The purpose of dynamic binding is to allow C# programs to interact with dynamic objects, i.e. objects that do not follow the normal rules of the C# type system. 動的オブジェクトは、異なる型システムを使用する他のプログラミング言語のオブジェクトである場合もあれば、異なる操作のために独自のバインディングセマンティクスを実装するようにプログラムで設定されるオブジェクトの場合もあります。Dynamic objects may be objects from other programming languages with different types systems, or they may be objects that are programmatically setup to implement their own binding semantics for different operations.

動的オブジェクトが独自のセマンティクスを実装する機構は、実装が定義されていることです。The mechanism by which a dynamic object implements its own semantics is implementation defined. 指定されたインターフェイス--再度実装が定義された--動的オブジェクトによって実装され、特殊なセマンティクスを持つことを C# ランタイムに通知します。A given interface -- again implementation defined -- is implemented by dynamic objects to signal to the C# run-time that they have special semantics. このため、動的オブジェクトに対する操作が動的にバインドされる場合は、このドキュメントで指定されている C# の動作ではなく、独自のバインディングセマンティクスが引き継がれます。Thus, whenever operations on a dynamic object are dynamically bound, their own binding semantics, rather than those of C# as specified in this document, take over.

動的バインドの目的は動的オブジェクトとの相互運用を可能にすることであるのに対し、C# では、動的バインドであるかどうかにかかわらず、すべてのオブジェクトに動的バインディングを使用できます。While the purpose of dynamic binding is to allow interoperation with dynamic objects, C# allows dynamic binding on all objects, whether they are dynamic or not. これにより、動的オブジェクトに対する操作の結果が動的なオブジェクトになるとは限りませんが、コンパイル時にはプログラマにとって未知の型になります。This allows for a smoother integration of dynamic objects, as the results of operations on them may not themselves be dynamic objects, but are still of a type unknown to the programmer at compile-time. また、動的バインドを使用すると、オブジェクトが動的オブジェクトに関連しない場合でも、エラーが発生しやすいリフレクションベースのコードを排除できます。Also dynamic binding can help eliminate error-prone reflection-based code even when no objects involved are dynamic objects.

次のセクションでは、動的バインドが適用されたときの言語の各構成要素、コンパイル時のチェック (適用されている場合)、およびコンパイル時の結果と式の分類について説明します。The following sections describe for each construct in the language exactly when dynamic binding is applied, what compile time checking -- if any -- is applied, and what the compile-time result and expression classification is.

構成式の型Types of constituent expressions

操作が静的にバインドされている場合、構成式の型 (たとえば、レシーバー、引数、インデックス、またはオペランド) は、常にその式のコンパイル時の型と見なされます。When an operation is statically bound, the type of a constituent expression (e.g. a receiver, an argument, an index or an operand) is always considered to be the compile-time type of that expression.

操作が動的にバインドされる場合、構成式の型は、構成式のコンパイル時の型に応じて、さまざまな方法で決定されます。When an operation is dynamically bound, the type of a constituent expression is determined in different ways depending on the compile-time type of the constituent expression:

  • コンパイル時の型の構成式は、 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

式は、オペランド _ および _演算子*_ から構築されます。Expressions are constructed from operands _ and _operators*_. 式の演算子は、オペランドに適用する演算を表します。The operators of an expression indicate which operations to apply to the operands. 演算子の例として、+-_/、および new などがあります。Examples of operators include +, -, _, /, and new. オペランドの例としては、リテラル、フィールド、ローカル変数、式などがあります。Examples of operands include literals, fields, local variables, and expressions.

演算子には、次の3種類があります。There are three kinds of operators:

  • 単項演算子。Unary operators. 単項演算子は、1つのオペランドを受け取り、プレフィックス表記 (など) --x または後置表記 (など) のいずれかを使用し x++ ます。The unary operators take one operand and use either prefix notation (such as --x) or postfix notation (such as x++).
  • 二項演算子。Binary operators. 二項演算子は、2つのオペランドを受け取り、すべて挿入辞表記 (など) を使用し x + y ます。The binary operators take two operands and all use infix notation (such as x + y).
  • 三項演算子。Ternary operator. 三項演算子は1つだけ ?: 存在します。3つのオペランドを受け取り、挿入辞表記 () を使用し c ? x : y ます。Only one ternary operator, ?:, exists; it takes three operands and uses infix notation (c ? x : y).

式における演算子の評価順序は、演算子の 優先順位 _ および _ 結合規則 (演算子の優先順位と結合規則) によって決まります。The order of evaluation of operators in an expression is determined by the precedence _ and _ associativity of the operators (Operator precedence and associativity).

式のオペランドは左から右に評価されます。Operands in an expression are evaluated from left to right. たとえば、では、 F(i) + G(i++) * H(i) メソッド F がの古い値を使用して呼び出された後、の前の値を使用してメソッドが呼び出され、 i G i 最後にの新しい値を使用してメソッドが呼び出され H i ます。For example, in F(i) + G(i++) * H(i), method F is called using the old value of i, then method G is called with the old value of i, and, finally, method H is called with the new value of i. これは、演算子の優先順位とは別のものです。This is separate from and unrelated to operator precedence.

特定の演算子は オーバーロード できます。Certain operators can be overloaded. 演算子のオーバーロードでは、一方または両方のオペランドがユーザー定義のクラスまたは構造体の型 (演算子のオーバーロード) である操作に対して、ユーザー定義の演算子の実装を指定できます。Operator overloading permits user-defined operator implementations to be specified for operations where one or both of the operands are of a user-defined class or struct type (Operator overloading).

演算子の優先順位と結合規則Operator precedence and associativity

式に複数の演算子が含まれている場合、演算子の *優先順位 は、個々の演算子が評価される順序を制御します。When an expression contains multiple operators, the *precedence _ of the operators controls the order in which the individual operators are evaluated. たとえば、式 x + y _ zx + (y * z) として評価されます。これは、演算子 * の優先順位が 2 項演算子 + よりも高いためです。For example, the expression x + y _ z is evaluated as x + (y * z) because the * operator has higher precedence than the binary + operator. 演算子の優先順位は、関連付けられている文法プロダクションの定義によって決定されます。The precedence of an operator is established by the definition of its associated grammar production. たとえば、 additive_expression は、または演算子で区切られた一連の multiplicative_expression で構成さ + - れます。したがって、演算子 + と演算子の優先順位は、、、およびの各 - 演算子よりも低く * / % なります。For example, an additive_expression consists of a sequence of multiplicative_expression s separated by + or - operators, thus giving the + and - operators lower precedence than the *, /, and % operators.

次の表は、すべての演算子を優先順位の高い順に示しています。The following table summarizes all operators in order of precedence from highest to lowest:

セクションSection カテゴリCategory オペレーターOperators
プライマリ式Primary expressions プライマリPrimary x.y f(x) a[x] x++ x-- new typeof default checked unchecked delegatex.y f(x) a[x] x++ x-- new typeof default checked unchecked delegate
単項演算子Unary operators 単項Unary + - ! ~ ++x --x (T)x+ - ! ~ ++x --x (T)x
算術演算子Arithmetic operators 乗法Multiplicative * / %* / %
算術演算子Arithmetic operators 加法Additive + -+ -
シフト演算子Shift operators ShiftShift << >><< >>
関係演算子と型検査演算子Relational and type-testing operators 関係式と型検査Relational and type testing < > <= >= is as< > <= >= is as
関係演算子と型検査演算子Relational and type-testing operators 等価比較Equality == !=== !=
論理演算子Logical operators 論理積Logical AND &
論理演算子Logical operators 論理 XORLogical XOR ^
論理演算子Logical operators 論理和Logical OR |
条件論理演算子Conditional logical operators 条件 ANDConditional AND &&
条件論理演算子Conditional logical operators 条件 ORConditional OR ||
null 合体演算子The null coalescing operator Null 合体演算子Null coalescing ??
条件演算子Conditional operator 条件付きConditional ?:
代入演算子匿名関数式Assignment operators, Anonymous function expressions 代入式とラムダ式Assignment and lambda expression = *= /= %= += -= <<= >>= &= ^= |= =>= *= /= %= += -= <<= >>= &= ^= |= =>

1 つのオペランドが同じ優先順位を持つ 2 つの演算子の間で発生した場合、演算子の結合性によって演算が実行される順序が決定されます。When an operand occurs between two operators with the same precedence, the associativity of the operators controls the order in which the operations are performed:

  • 代入演算子および 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) + z と評価されます。For 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 = zx = (y = z) と評価されます。For example, x = y = z is evaluated as x = (y = z).

優先順位と結合性は、かっこを使用して制御することができます。Precedence and associativity can be controlled using parentheses. たとえば、x + y * z は最初に yz を掛け、そして結果を x に足しますが、(x + y) * z では最初に xy を足してから z を掛けます。For example, x + y * z first multiplies y by z and then adds the result to x, but (x + y) * z first adds x and y and then multiplies the result by z.

演算子のオーバーロードOperator overloading

すべての単項演算子と二項演算子には、任意の式で自動的に使用できる定義済みの実装があります。All unary and binary operators have predefined implementations that are automatically available in any expression. 定義済みの実装に加えて、 operator クラスと構造体 (演算子) に宣言を含めることによって、ユーザー定義の実装を導入することができます。In addition to the predefined implementations, user-defined implementations can be introduced by including operator declarations in classes and structs (Operators). ユーザー定義の演算子の実装は、常に定義済みの演算子の実装よりも優先されます。ユーザー定義の演算子の実装が存在しない場合のみ、 単項演算子のオーバーロードの解決二項演算子のオーバーロードの解決に関するページで説明されているように、定義済みの演算子の実装が考慮されます。User-defined operator implementations always take precedence over predefined operator implementations: Only when no applicable user-defined operator implementations exist will the predefined operator implementations be considered, as described in Unary operator overload resolution and Binary operator overload resolution.

オーバーロード可能な 単項演算子 は次のとおりです。The overloadable unary operators are:

+   -   !   ~   ++   --   true   false

truefalse は、式で明示的に使用されていません (したがって、演算子の優先順位と結合規則の優先順位テーブルには含まれません) が、演算子と見なされます。これは、ブール式 (ブール式) と条件付き論理演算子 (条件付き演算子) を含む式 (条件付き論理演算子) で呼び出されるためです。Although true and false are not used explicitly in expressions (and therefore are not included in the precedence table in Operator precedence and associativity), they are considered operators because they are invoked in several expression contexts: boolean expressions (Boolean expressions) and expressions involving the conditional (Conditional operator), and conditional logical operators (Conditional logical operators).

オーバーロードされた 二項演算子 は次のとおりです。The overloadable binary operators are:

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

上に示した演算子のみをオーバーロードできます。Only the operators listed above can be overloaded. 特に、メンバーアクセス、メソッド呼び出し、、、、、、、、、、、、、、およびの各演算子をオーバーロードすることはできません = && || ?? ?: => checked unchecked new typeof default as isIn particular, it is not possible to overload member access, method invocation, or the =, &&, ||, ??, ?:, =>, checked, unchecked, new, typeof, default, as, and is operators.

二項演算子をオーバーロードすると、対応する代入演算子がある場合、これも暗黙的にオーバーロードされます。When a binary operator is overloaded, the corresponding assignment operator, if any, is also implicitly overloaded. たとえば、演算子のオーバーロードは、 * 演算子のオーバーロードでも *= あります。For example, an overload of operator * is also an overload of operator *=. 詳細については、「 複合代入」を参照してください。This is described further in Compound assignment. 代入演算子自体 ( = ) はオーバーロードできないことに注意してください。Note that the assignment operator itself (=) cannot be overloaded. 代入は常に、値の単純なビット単位のコピーを変数に対して実行します。An assignment always performs a simple bit-wise copy of a value into a variable.

などのキャスト操作 (T)x は、ユーザー定義の変換 (ユーザー定義の変換) を提供することによってオーバーロードされます。Cast operations, such as (T)x, are overloaded by providing user-defined conversions (User-defined conversions).

などの要素アクセス a[x] は、オーバーロード可能な演算子とは見なされません。Element access, such as a[x], is not considered an overloadable operator. 代わりに、インデクサー (インデクサー) を使用してユーザー定義のインデックス作成がサポートされます。Instead, user-defined indexing is supported through indexers (Indexers).

式では、演算子は演算子表記を使用して参照され、宣言では、演算子は関数表記を使用して参照されます。In expressions, operators are referenced using operator notation, and in declarations, operators are referenced using functional notation. 次の表は、単項演算子と二項演算子の演算子と関数表記の関係を示しています。The following table shows the relationship between operator and functional notations for unary and binary operators. 最初のエントリで、 op はオーバーロードされた単項前置演算子を表します。In the first entry, op denotes any overloadable unary prefix operator. 2番目のエントリでは、 op は単項接尾辞 ++ と演算子を表し -- ます。In the second entry, op denotes the unary postfix ++ and -- operators. 3番目のエントリでは、 op はオーバーロード可能な任意の二項演算子を表します。In the third entry, op denotes any overloadable binary operator.

演算子の表記Operator notation 関数型表記Functional notation
op x operator op(x)
x op operator op(x)
x op y operator op(x,y)

ユーザー定義の演算子宣言には、常に、演算子宣言を含むクラスまたは構造体型のパラメーターが少なくとも1つ必要です。User-defined operator declarations always require at least one of the parameters to be of the class or struct type that contains the operator declaration. したがって、ユーザー定義の演算子は、定義済みの演算子と同じシグネチャを持つことはできません。Thus, it is not possible for a user-defined operator to have the same signature as a predefined operator.

ユーザー定義の演算子宣言では、演算子の構文、優先順位、または結合規則を変更できません。User-defined operator declarations cannot modify the syntax, precedence, or associativity of an operator. たとえば、演算子は / 常に二項演算子であり、常に 演算子の優先順位と結合規則で指定された優先順位レベルを持ち、常に左結合です。For example, the / operator is always a binary operator, always has the precedence level specified in Operator precedence and associativity, and is always left-associative.

ユーザー定義の演算子は、pleases の計算を実行することができますが、直感的に想定されているもの以外の結果を生成する実装は避けることを強くお勧めします。While it is possible for a user-defined operator to perform any computation it pleases, implementations that produce results other than those that are intuitively expected are strongly discouraged. たとえば、の実装では、 operator == 2 つのオペランドが等しいかどうかを比較し、適切な結果を返す必要があり bool ます。For example, an implementation of operator == should compare the two operands for equality and return an appropriate bool result.

条件付き論理演算子を使用した主な式の各演算子の説明では、演算子の定義済みの実装と、各演算子に適用される追加の規則を指定します。The descriptions of individual operators in Primary expressions through Conditional logical operators specify the predefined implementations of the operators and any additional rules that apply to each operator. 説明では、次のセクションで説明するように、単項演算子のオーバーロードの解決 _、 _二項演算子のオーバーロードの解決_、および _ * 数値の 昇格 * という用語を使用します。The descriptions make use of the terms unary operator overload resolution _, _binary operator overload resolution_, and _numeric promotion**, definitions of which are found in the following sections.

単項演算子のオーバーロードの解決Unary operator overload resolution

またはの形式の演算 ( op x x op op はオーバーロード可能な単項演算子で、は型の式) は、次のように x X 処理されます。An operation of the form op x or x op, where op is an overloadable unary operator, and x is an expression of type X, is processed as follows:

  • 操作のためにによって提供される一連のユーザー定義演算子 X operator op(x) は、 ユーザー定義の候補演算子の規則を使用して決定されます。The set of candidate user-defined operators provided by X for the operation operator op(x) is determined using the rules of Candidate user-defined operators.
  • 一連のユーザー定義演算子が空でない場合は、これが操作の候補演算子のセットになります。If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. それ以外の場合、定義済みの単項実装 (リフトされた operator op 形式を含む) は、操作の候補演算子のセットになります。Otherwise, the predefined unary operator op implementations, including their lifted forms, become the set of candidate operators for the operation. 特定の演算子の定義済みの実装は、演算子の説明 (主な および 単項演算子) で指定されます。The predefined implementations of a given operator are specified in the description of the operator (Primary expressions and Unary operators).
  • オーバーロード解決のオーバーロード解決規則は、引数リストに対して最適な演算子を選択する候補演算子のセットに適用され (x) ます。この演算子は、オーバーロードの解決プロセスの結果になります。The overload resolution rules of Overload resolution are applied to the set of candidate operators to select the best operator with respect to the argument list (x), and this operator becomes the result of the overload resolution process. オーバーロードの解決で1つの最適な演算子を選択できなかった場合、バインド時エラーが発生します。If overload resolution fails to select a single best operator, a binding-time error occurs.

二項演算子のオーバーロードの解決Binary operator overload resolution

フォームの操作 x op y 。ここで、 op はオーバーロード可能な二項演算子、は x 型の式、は X 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:

  • 操作のために、およびによって提供される一連の候補ユーザー定義演算子 X Y operator op(x,y) が決定されます。The set of candidate user-defined operators provided by X and Y for the operation operator op(x,y) is determined. このセットは、によって提供される候補演算子と、によって提供される候補演算子の和集合で構成され X Y ます。各演算子は、 ユーザー定義演算子の候補の規則を使用して決定されます。The set consists of the union of the candidate operators provided by X and the candidate operators provided by Y, each determined using the rules of Candidate user-defined operators. XY が同じ型である場合、または X とが共通の基本型から派生している場合 Y 、共有候補演算子は結合セット内で1回だけ発生します。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. オーバーロードの解決で1つの最適な演算子を選択できなかった場合、バインド時エラーが発生します。If overload resolution fails to select a single best operator, a binding-time error occurs.

ユーザー定義演算子の候補Candidate user-defined operators

型と操作が指定されて T operator op(A) いる場合 (はオーバーロード可能な演算子であり、は op A 引数リスト)、によって提供される候補ユーザー定義演算子のセット T operator op(A) は次のように決定されます。Given a type T and an operation operator op(A), where op is an overloadable operator and A is an argument list, the set of candidate user-defined operators provided by T for operator op(A) is determined as follows:

  • 型を決定 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.
  • 内のすべての operator op 宣言 T0 と、そのような演算子のすべてのリフトされた形式では、引数リストに対して少なくとも1つの演算子 (適用可能な関数メンバー) が適用される場合、 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.
  • それ以外の場合、がの場合、 T0 object 候補演算子のセットは空になります。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

数値の上位変換は、定義済みの単項演算子と二項数値演算子のオペランドの特定の暗黙的な変換を自動的に実行することで構成されます。Numeric promotion consists of automatically performing certain implicit conversions of the operands of the predefined unary and binary numeric operators. 数値の上位変換は個別のメカニズムではなく、定義済みの演算子にオーバーロードの解決を適用した場合の効果です。Numeric promotion is not a distinct mechanism, but rather an effect of applying overload resolution to the predefined operators. 数値の上位変換は、特にユーザー定義の演算子の評価には影響しませんが、同様の効果をもたらすためにユーザー定義の演算子を実装することはできます。Numeric promotion specifically does not affect evaluation of user-defined operators, although user-defined operators can be implemented to exhibit similar effects.

数値の上位変換の例として、二項演算子の定義済みの実装について考えてみましょう *As an example of numeric promotion, consider the predefined implementations of the binary * operator:

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);

オーバーロードの解決規則 (オーバーロードの解決) がこの一連の演算子に適用される場合、結果として、オペランドの型から暗黙的な変換が存在する最初の演算子が選択されます。When overload resolution rules (Overload resolution) are applied to this set of operators, the effect is to select the first of the operators for which implicit conversions exist from the operand types. たとえば、がで、がである操作の場合、 b * s b オーバーロードの解決は byte s short operator *(int,int) 最適な演算子としてを選択します。For example, for the operation b * s, where b is a byte and s is a short, overload resolution selects operator *(int,int) as the best operator. したがって、 bs はに変換され、 int 結果の型はになり int ます。Thus, the effect is that b and s are converted to int, and the type of the result is int. 同様に、操作では、はで、 i * d i int d はです double 。オーバーロードの解決は、 operator *(double,double) 最適な演算子としてを選択します。Likewise, for the operation i * d, where i is an int and d is a double, overload resolution selects operator *(double,double) as the best operator.

単項数値の上位変換Unary numeric promotions

単項数値の上位変換は、定義済みの +- 、および単項演算子のオペランドに対して行わ ~ れます。Unary numeric promotion occurs for the operands of the predefined +, -, and ~ unary operators. 単項数値の上位変換は、、、 sbytebyte 、または型のオペランドを型に変換するだけで構成さ short ushort char int れます。Unary numeric promotion simply consists of converting operands of type sbyte, byte, short, ushort, or char to type int. さらに、単項演算子の場合、 - 単項演算子は型のオペランド uint を型に変換し long ます。Additionally, for the unary - operator, unary numeric promotion converts operands of type uint to type long.

バイナリ数値の上位変換Binary numeric promotions

バイナリ数値の上位変換は、定義済み、、、、、、、、、、、、、およびの各二項演算子のオペランドに対して行わ + - * / % & | ^ == != > < >= <= れます。Binary numeric promotion occurs for the operands of the predefined +, -, *, /, %, &, |, ^, ==, !=, >, <, >=, and <= binary operators. バイナリ数値の昇格では、両方のオペランドが共通の型に暗黙的に変換されます。これは、非関係演算子の場合、演算の結果の型にもなります。Binary numeric promotion implicitly converts both operands to a common type which, in case of the non-relational operators, also becomes the result type of the operation. バイナリ数値の上位変換では、次のルールがここに表示される順序で適用されます。Binary numeric promotion consists of applying the following rules, in the order they appear here:

  • いずれかのオペランドが型の場合、もう一方のオペランドが型 decimal に変換される decimal か、もう一方のオペランドがまたは型である場合は、バインディング時エラーが発生し float double ます。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 もう一方のオペランドは型に変換され double ます。Otherwise, if either operand is of type double, the other operand is converted to type double.
  • それ以外の場合、いずれかのオペランドが型の場合、 float もう一方のオペランドは型に変換され float ます。Otherwise, if either operand is of type float, the other operand is converted to type float.
  • それ以外の場合、いずれかのオペランドが型である場合、もう一方のオペランドが型 ulong に変換される ulong か、もう一方のオペランドが sbyte 、、 short int 、または型である場合は、バインディング時エラーが発生し long ます。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 もう一方のオペランドは型に変換され long ます。Otherwise, if either operand is of type long, the other operand is converted to type long.
  • それ以外の場合、いずれかのオペランドが型で、 uint もう一方のオペランドが、、または型である場合、 sbyte 両方のオペランドが short int 型に変換され long ます。Otherwise, 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 もう一方のオペランドは型に変換され uint ます。Otherwise, if either operand is of type uint, the other operand is converted to type uint.
  • それ以外の場合、両方のオペランドが型に変換され int ます。Otherwise, both operands are converted to type int.

1つ目のルールでは、型と型を混在させる操作は許可されないことに注意して decimal double float ください。Note that the first rule disallows any operations that mix the decimal type with the double and float types. この規則は、型と型および型との間に暗黙的な変換が存在しないという事実から続き decimal double float ます。The rule follows from the fact that there are no implicit conversions between the decimal type and the double and float types.

ulongもう一方のオペランドが符号付き整数型の場合、オペランドを型にすることはできないことにも注意してください。Also note that it is not possible for an operand to be of type ulong when the other operand is of a signed integral type. これは、の完全な範囲と ulong 符号付き整数型を表すことができる整数型が存在しないためです。The reason is that no integral type exists that can represent the full range of ulong as well as the signed integral types.

どちらの場合も、キャスト式を使用して、あるオペランドを他のオペランドと互換性のある型に明示的に変換できます。In both of the above cases, a cast expression can be used to explicitly convert one operand to a type that is compatible with the other operand.

この例では、In the example

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

にを decimal 乗算することはできないため、バインド時エラーが発生し double ます。a binding-time error occurs because a decimal cannot be multiplied by a double. このエラーは、次のように、2番目のオペランドをに明示的に変換することによって解決され decimal ます。The error is resolved by explicitly converting the second operand to decimal, as follows:

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

リフト演算子Lifted operators

リフト された演算子を使用すると、null 非許容の値型を操作する定義済みの演算子とユーザー定義の演算子を、これらの型の null 許容形式でも使用できます。Lifted operators permit predefined and user-defined operators that operate on non-nullable value types to also be used with nullable forms of those types. リフトされた演算子は、以下で説明するように、特定の要件を満たす定義済み演算子およびユーザー定義演算子から構築されます。Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following:

  • 単項演算子の場合For the unary operators

    +  ++  -  --  !  ~
    

    オペランドと結果の型が両方とも null 非許容の値型である場合、演算子のリフトされた形式が存在します。a lifted form of an operator exists if the operand and result types are both non-nullable value types. リフトされたフォームは、 ? オペランドと結果の型に1つの修飾子を追加することによって構築されます。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. リフトされた形式を作成するには、 ? 各オペランドと結果の型に1つの修飾子を追加します。The lifted form is constructed by adding a single ? modifier to each operand and result type. リフトされた演算子は、一方または両方のオペランドが null の場合、null 値を生成し & | ます ( bool?ブール論理演算子」で説明されているように、型のおよび演算子である例外)。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. リフトされた形式は、各オペランド型に1つの修飾子を追加することによって作成され ? ます。The lifted form is constructed by adding a single ? modifier to each operand type. リフトされた演算子は、2つの null 値が等しいと見なされ、null 値は null 以外の値と等しくなりません。The lifted operator considers two null values equal, and a null value unequal to any non-null value. 両方のオペランドが null 以外の場合、リフトされた演算子はオペランドのラップを解除し、基になる演算子を適用して結果を生成し bool ます。If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

  • 関係演算子For the relational operators

    <  >  <=  >=
    

    オペランドの型が null 非許容の値型であり、結果の型がの場合、演算子のリフトされた形式が存在し bool ます。a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. リフトされた形式は、各オペランド型に1つの修飾子を追加することによって作成され ? ます。The lifted form is constructed by adding a single ? modifier to each operand type. リフトされた演算子は、 false 一方または両方のオペランドが null の場合に値を生成します。The 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

メンバー参照とは、型のコンテキストにおける名前の意味が決定されるプロセスです。A member lookup is the process whereby the meaning of a name in the context of a type is determined. メンバー参照は、式での simple_name (簡易名) または member_access (メンバーアクセス) の評価の一部として発生することがあります。A member lookup can occur as part of evaluating a simple_name (Simple names) or a member_access (Member access) in an expression. Simple_name または member_accessinvocation_expression (メソッド呼び出し) の primary_expression として発生した場合、メンバーは呼び出されていると言います。If the simple_name or member_access occurs as the primary_expression of an invocation_expression (Method invocations), the member is said to be invoked.

メンバーがメソッドまたはイベントである場合、またはデリゲート型 (デリゲート) または型 (動的型) の定数、フィールド、またはプロパティである場合、 dynamic メンバーは invocable呼ばれます。If a member is a method or event, or if it is a constant, field or property of either a delegate type (Delegates) or the type dynamic (The dynamic type), then the member is said to be invocable.

メンバーの検索では、メンバーの名前だけでなく、メンバーに含まれる型パラメーターの数と、メンバーにアクセスできるかどうかも考慮されます。Member lookup considers not only the name of a member but also the number of type parameters the member has and whether the member is accessible. メンバー参照のために、ジェネリックメソッドと入れ子になったジェネリック型にはそれぞれの宣言で指定された型パラメーターの数があり、他のすべてのメンバーにはゼロ型パラメーターがあります。For the purposes of member lookup, generic methods and nested generic types have the number of type parameters indicated in their respective declarations and all other members have zero type parameters.

型の型パラメーターを持つ名前のメンバー参照  N K   は、  T 次のように処理されます。A member lookup of a name N with K type parameters in a type T is processed as follows:

  • 最初に、という名前のアクセス可能なメンバーのセット  N が決定されます。First, a set of accessible members named N is determined:
    • Tが型パラメーターの場合、セットは、  N のプライマリ制約またはセカンダリ制約 (型パラメーター制約) として指定された各型のという名前のアクセス可能なメンバーのセットを  T 、のという名前のアクセス可能なメンバーのセットと共に結合したものになり  N object ます。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.
    • それ以外の場合、セットは、内のという名前のアクセス可能な (メンバーアクセス) すべてのメンバーで構成されます。これには、継承された  N  T メンバーや、のという名前のユーザー補助メンバー  N objectOtherwise, 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が0でない場合は、型パラメーターの数が異なるメンバーがすべて削除されます。If K is not zero, all members with a different number of type parameters are removed. がゼロの場合、型 K パラメーターを持つメソッドは削除されません。これは、型の推論プロセス (型の推定) が型引数を推論できる可能性があるためです。Note that when K is zero, methods having type parameters are not removed, since the type inference process (Type inference) might be able to infer the type arguments.
  • 次に、メンバーが 呼び出さ れると、invocable 以外のすべてのメンバーがセットから削除されます。Next, if the member is invoked, all non-invocable members are removed from the set.
  • 次に、他のメンバーによって非表示になっているメンバーがセットから削除されます。Next, members that are hidden by other members are removed from the set. セット内のすべてのメンバーについて、はメンバーが宣言されている型であるため、 S.M S  M 次の規則が適用されます。For every member S.M in the set, where S is the type in which the member M is declared, the following rules are applied:
    • Mが定数、フィールド、プロパティ、イベント、または列挙型のメンバーである場合は、の基本型で宣言されたすべてのメンバー S がセットから削除されます。If M is a constant, field, property, event, or enumeration member, then all members declared in a base type of S are removed from the set.
    • Mが型宣言の場合、基本型で宣言されているすべての非型 S がセットから削除され、 M の基本型で宣言されているものと同じ数の型パラメーターを持つすべての型宣言が S セットから削除されます。If M is a type declaration, then all non-types declared in a base type of S are removed from the set, and all type declarations with the same number of type parameters as M declared in a base type of S are removed from the set.
    • Mがメソッドの場合は、の基本型で宣言されているすべての非メソッドメンバー S がセットから削除されます。If M is a method, then all non-method members declared in a base type of S are removed from the set.
  • 次に、クラスメンバーによって隠ぺいされたインターフェイスメンバーがセットから削除されます。Next, interface members that are hidden by class members are removed from the set. このステップは、 T が型パラメーターであり、 T object かつ、かつ空でない有効なインターフェイスセット (型パラメーター制約) 以外の有効な基本クラスを持っている場合にのみ効果があります。This step only has an effect if T is a type parameter and T has both an effective base class other than object and a non-empty effective interface set (Type parameter constraints). セット内のすべてのメンバーについて S.M 、は S メンバー M が宣言されている型です 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:
    • セットが、メソッドではない1つのメンバーで構成されている場合、このメンバーは参照の結果になります。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.

型パラメーターとインターフェイス以外の型のメンバー参照、および厳密に単一継承であるインターフェイス内のメンバー参照 (継承チェーンの各インターフェイスには、完全に0または1つの直接基底インターフェイスがある) の場合、検索規則の効果は、派生メンバーが同じ名前またはシグネチャを持つ基本メンバーを隠ぺいするだけです。For member lookups in types other than type parameters and interfaces, and member lookups in interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effect of the lookup rules is simply that derived members hide base members with the same name or signature. このような単一継承の参照があいまいになることはありません。Such single-inheritance lookups are never ambiguous. 複数継承インターフェイスのメンバー参照で生じる可能性があるあいまいさについては、「 インターフェイスメンバーアクセス」を参照してください。The ambiguities that can possibly arise from member lookups in multiple-inheritance interfaces are described in Interface member access.

基本型Base types

メンバー検索の目的では、型 T は次の基本型を持つと見なされます。For purposes of member lookup, a type T is considered to have the following base types:

  • Tobject の場合、 T には基本型がありません。If T is object, then T has no base type.
  • Tenum_type の場合、の基本型は、、、 T System.Enum System.ValueType および object です。If T is an enum_type, the base types of T are the class types System.Enum, System.ValueType, and object.
  • Tstruct_type の場合、の基本型は T とのクラス型 System.ValueType です objectIf T is a struct_type, the base types of T are the class types System.ValueType and object.
  • Tclass_type の場合、の基本型 TT 、クラス型を含むの基本クラスです 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 およびクラス型の基本インターフェイスです objectIf 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.Array です objectIf T is an array_type, the base types of T are the class types System.Array and object.
  • Tdelegate_type の場合、の基本型は T とのクラス型 System.Delegate です objectIf T is a delegate_type, the base types of T are the class types System.Delegate and object.

関数メンバーFunction members

関数メンバーは、実行可能なステートメントを含むメンバーです。Function members are members that contain executable statements. 関数メンバーは常に型のメンバーであり、名前空間のメンバーになることはできません。Function members are always members of types and cannot be members of namespaces. C# では、次のカテゴリの関数メンバーが定義されています。C# defines the following categories of function members:

  • メソッドMethods
  • プロパティProperties
  • イベントEvents
  • インデクサーIndexers
  • ユーザー定義演算子User-defined operators
  • インスタンスコンストラクターInstance constructors
  • 静的コンストラクターStatic constructors
  • デストラクターDestructors

デストラクターと静的コンストラクター (明示的に呼び出すことはできません) を除き、関数メンバーに含まれるステートメントは、関数メンバー呼び出しを通じて実行されます。Except for destructors and static constructors (which cannot be invoked explicitly), the statements contained in function members are executed through function member invocations. 関数メンバー呼び出しを記述する実際の構文は、特定の関数メンバーカテゴリによって異なります。The actual syntax for writing a function member invocation depends on the particular function member category.

関数メンバー呼び出しの引数リスト (引数リスト) は、関数メンバーのパラメーターに対する実際の値または変数参照を提供します。The argument list (Argument lists) of a function member invocation provides actual values or variable references for the parameters of the function member.

ジェネリックメソッドの呼び出しでは、型の推定を使用して、メソッドに渡す型引数のセットを決定できます。Invocations of generic methods may employ type inference to determine the set of type arguments to pass to the method. このプロセスについては、 「型の推定」を参照してください。This process is described in Type inference.

メソッド、インデクサー、演算子、およびインスタンスコンストラクターの呼び出しは、オーバーロードの解決を使用して、呼び出し元の候補となる関数メンバーのセットを決定します。Invocations of methods, indexers, operators and instance constructors employ overload resolution to determine which of a candidate set of function members to invoke. このプロセスの詳細については、「 オーバーロードの解決」を参照してください。This process is described in Overload resolution.

バインディング時に特定の関数メンバーが特定された後、場合によってはオーバーロードの解決によって、関数メンバーを呼び出す実際の実行時プロセスについては、「 動的なオーバーロードの解決のコンパイル時のチェック」で説明されています。Once a particular function member has been identified at binding-time, possibly through overload resolution, the actual run-time process of invoking the function member is described in Compile-time checking of dynamic overload resolution.

次の表は、明示的に呼び出すことができる関数メンバーの6つのカテゴリを含む構造体で行われる処理をまとめたものです。The following table summarizes the processing that takes place in constructs involving the six categories of function members that can be explicitly invoked. テーブルで、、 ex y 、およびは、 value 変数または値として分類される式を示し T ます。は、型として分類される式、 F はメソッドの単純な名前、 P はプロパティの簡易名です。In the table, e, x, y, and value indicate expressions classified as variables or values, T indicates an expression classified as a type, F is the simple name of a method, and P is the simple name of a property.

構築Construct Example 説明Description
メソッドの呼び出しMethod invocation F(x,y) オーバーロードの解決は F 、含んでいるクラスまたは構造体の中で最適なメソッドを選択するために適用されます。Overload resolution is applied to select the best method F in the containing class or struct. 引数リストを使用してメソッドが呼び出され (x,y) ます。The method is invoked with the argument list (x,y). メソッドがでない場合 static 、インスタンス式は this です。If the method is not static, the instance expression is this.
T.F(x,y) オーバーロードの解決は F 、クラスまたは構造体で最適なメソッドを選択するために適用され T ます。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) オーバーロードの解決は、の型によって指定されたクラス、構造体、またはインターフェイスで最適なメソッド F を選択するために適用され e ます。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 get P 含んでいるクラスまたは構造体のプロパティのアクセサーが呼び出されます。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. Pがでない場合 static 、インスタンス式は this です。If P is not static, the instance expression is this.
P = value set P 含んでいるクラスまたは構造体のプロパティのアクセサーが、引数リストを使用して呼び出され (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. Pがでない場合 static 、インスタンス式は this です。If P is not static, the instance expression is this.
T.P get P クラスまたは構造体のプロパティのアクセサー T が呼び出されます。The get accessor of the property P in the class or struct T is invoked. がでない場合、または P が書き込み専用の場合、コンパイル時エラーが発生し static P ます。A compile-time error occurs if P is not static or if P is write-only.
T.P = value set P クラスまたは構造体のプロパティのアクセサー T は、引数リストを使用して呼び出され (value) ます。The set accessor of the property P in the class or struct T is invoked with the argument list (value). がでない場合、またはが読み取り専用の場合、コンパイル時エラーが発生し P static P ます。A compile-time error occurs if P is not static or if P is read-only.
e.P get P の型によって指定されたクラス、構造体、またはインターフェイスのプロパティのアクセサー e は、インスタンス式を使用して呼び出され 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 static またはが書き込み専用の場合、バインド時エラーが発生し P ます。A binding-time error occurs if P is static or if P is write-only.
e.P = value set P の型によって指定されたクラス、構造体、またはインターフェイスのプロパティのアクセサー e は、インスタンス式および引数リストを使用して呼び出され 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 static P ます。A binding-time error occurs if P is static or if P is read-only.
イベントアクセスEvent access E += value add E 含んでいるクラスまたは構造体のイベントのアクセサーが呼び出されます。The add 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.
E -= value remove E 含んでいるクラスまたは構造体のイベントのアクセサーが呼び出されます。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 add E クラスまたは構造体のイベントのアクセサー T が呼び出されます。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 remove E クラスまたは構造体のイベントのアクセサー T が呼び出されます。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 add E の型によって指定されたクラス、構造体、またはインターフェイスのイベントのアクセサー e は、インスタンス式を使用して呼び出され 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 remove E の型によって指定されたクラス、構造体、またはインターフェイスのイベントのアクセサー e は、インスタンス式を使用して呼び出され 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.
インデクサーへのアクセスIndexer access e[x,y] オーバーロードの解決は、e の型によって指定されたクラス、構造体、またはインターフェイスで最適なインデクサーを選択するために適用されます。Overload resolution is applied to select the best indexer in the class, struct, or interface given by the type of e. getインデクサーのアクセサーは、インスタンス式と引数リストを使用して呼び出され e (x,y) ます。The get accessor of the indexer is invoked with the instance expression e and the argument list (x,y). インデクサーが書き込み専用の場合、バインド時エラーが発生します。A binding-time error occurs if the indexer is write-only.
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.
演算子の呼び出しOperator invocation -x オーバーロードの解決は、の型によって指定されたクラスまたは構造体の中で最適な単項演算子を選択するために適用され x ます。Overload resolution is applied to select the best unary operator in the class or struct given by the type of x. 選択した演算子が引数リストと共に呼び出され (x) ます。The selected operator is invoked with the argument list (x).
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).
インスタンスコンストラクターの呼び出しInstance constructor invocation new T(x,y) オーバーロードの解決は、クラスまたは構造体で最適なインスタンスコンストラクターを選択するために適用され T ます。Overload resolution is applied to select the best instance constructor in the class or struct T. インスタンスコンストラクターは、引数リストと共に呼び出され (x,y) ます。The instance constructor is invoked with the argument list (x,y).

引数リストArgument lists

すべての関数メンバーとデリゲートの呼び出しには、関数メンバーのパラメーターの実際の値または変数参照を提供する引数リストが含まれています。Every function member and delegate invocation includes an argument list which provides actual values or variable references for the parameters of the function member. 関数メンバー呼び出しの引数リストを指定する構文は、関数メンバーカテゴリによって異なります。The syntax for specifying the argument list of a function member invocation depends on the function member category:

  • インスタンスコンストラクター、メソッド、インデクサー、およびデリゲートでは、次に示すように、引数が 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.
  • イベントの場合、引数リストは、or 演算子の右オペランドとして指定された式で構成され += -= ます。For events, the argument list consists of the expression specified as the right operand of the += or -= operator.
  • ユーザー定義演算子の場合、引数リストは単項演算子の1つのオペランド、または二項演算子の2つのオペランドで構成されます。For user-defined operators, the argument list consists of the single operand of the unary operator or the two operands of the binary operator.

プロパティ (プロパティ)、イベント (イベント)、およびユーザー定義演算子 (演算子) の引数は、常に値パラメーター (値パラメーター) として渡されます。The arguments of properties (Properties), events (Events), and user-defined operators (Operators) are always passed as value parameters (Value parameters). インデクサー (インデクサー) の引数は、常に値パラメーター (値パラメーター) またはパラメーター配列 (パラメーター配列) として渡されます。The arguments of indexers (Indexers) are always passed as value parameters (Value parameters) or parameter arrays (Parameter arrays). 参照パラメーターと出力パラメーターは、これらのカテゴリの関数メンバーではサポートされていません。Reference and output parameters are not supported for these categories of function members.

インスタンスコンストラクター、メソッド、インデクサー、またはデリゲートの呼び出しの引数は、 argument_list として指定されます。The arguments of an instance constructor, method, indexer or delegate invocation are specified as an argument_list:

argument_list
    : argument (',' argument)*
    ;

argument
    : argument_name? argument_value
    ;

argument_name
    : identifier ':'
    ;

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

Argument_list は、コンマで区切られた1つ以上の 引数 で構成されます。An argument_list consists of one or more argument s, separated by commas. 各引数は、省略可能な argument_name とそれに続く argument_value で構成されます。Each argument consists of an optional argument_name followed by an argument_value. Argument_name を持つ 引数 は *名前付き引数 _ と呼ばれ、 *argument_name* のない引数 * は *位置指定引数 です。An argument with an argument_name is referred to as a named argument _, whereas an _argument without an argument_name is a *positional argument_. _Argument_list * の名前付き引数の後に位置引数を指定すると、エラーになります。It is an error for a positional argument to appear after a named argument in an _argument_list*.

Argument_value は、次のいずれかの形式を取ることができます。The argument_value can take one of the following forms:

  • 値パラメーター (値パラメーター) として引数が渡されることを示す An expression, indicating that the argument is passed as a value parameter (Value parameters).
  • キーワードの ref 後に variable_reference (変数参照) が続く場合は、引数が参照パラメーター (参照パラメーター) として渡されることを示します。The keyword ref followed by a variable_reference (Variable references), indicating that the argument is passed as a reference parameter (Reference parameters). 参照パラメーターとして渡すには、変数を確実に代入 (明確な代入) する必要があります。A variable must be definitely assigned (Definite assignment) before it can be passed as a reference parameter. キーワードの out 後に variable_reference (変数参照) が続く場合は、引数が出力パラメーター (出力パラメーター) として渡されることを示します。The keyword out followed by a variable_reference (Variable references), indicating that the argument is passed as an output parameter (Output parameters). 変数は、出力パラメーターとして渡される関数メンバー呼び出しの後に、確実に代入 (明確な代入) と見なされます。A variable is considered definitely assigned (Definite assignment) following a function member invocation in which the variable is passed as an output parameter.

対応するパラメーターCorresponding parameters

引数リストの引数ごとに、呼び出される関数メンバーまたはデリゲートに対応するパラメーターが必要です。For each argument in an argument list there has to be a corresponding parameter in the function member or delegate being invoked.

次のように使用されるパラメーターリストは、次のように決定されます。The parameter list used in the following is determined as follows:

  • クラスで定義された仮想メソッドとインデクサーの場合、パラメーターリストは、受信側の静的な型から開始し、その基本クラスを検索することで、関数メンバーの最も限定的な宣言またはオーバーライドから選択されます。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.
  • 他のすべての関数メンバーとデリゲートでは、1つのパラメーターリストのみが使用されます。For all other function members and delegates there is only a single parameter list, which is the one used.

引数またはパラメーターの位置は、引数リストまたはパラメーターリストの前にある引数またはパラメーターの数として定義されます。The position of an argument or parameter is defined as the number of arguments or parameters preceding it in the argument list or parameter list.

関数メンバー引数の対応するパラメーターは、次のように設定されます。The corresponding parameters for function member arguments are established as follows:

  • インスタンスコンストラクター、メソッド、インデクサー、およびデリゲートの 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 代入演算子の右オペランドとして指定された式が、 value アクセサー宣言の暗黙的なパラメーターに対応し set ます。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 、代入演算子の右オペランドとして指定された式は、 value アクセサー宣言の暗黙的なパラメーターに対応し set ます。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.
  • ユーザー定義の単項演算子 (変換を含む) の場合、1つのオペランドは演算子宣言の1つのパラメーターに対応します。For user-defined unary operators (including conversions), the single operand corresponds to the single parameter of the operator declaration.
  • ユーザー定義の二項演算子の場合、左側のオペランドは最初のパラメーターに対応し、右のオペランドは演算子宣言の2番目のパラメーターに対応します。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

関数メンバー呼び出しの実行時の処理中 (動的なオーバーロード解決のコンパイル時のチェック) では、引数リストの式または変数の参照は、左から右の順に、次のように評価されます。During the run-time processing of a function member invocation (Compile-time checking of dynamic overload resolution), the expressions or variable references of an argument list are evaluated in order, from left to right, as follows:

  • 値パラメーターの場合、引数式が評価され、対応するパラメーター型への暗黙的な変換 (暗黙の変換) が実行されます。For a value parameter, the argument expression is evaluated and an implicit conversion (Implicit conversions) to the corresponding parameter type is performed. 結果の値は、関数メンバー呼び出しの値パラメーターの初期値になります。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.ArrayTypeMismatchException がスローされます。If this check fails, a System.ArrayTypeMismatchException is thrown.

メソッド、インデクサー、およびインスタンスコンストラクターは、右端のパラメーターをパラメーター配列 (パラメーター配列) として宣言できます。Methods, indexers, and instance constructors may declare their right-most parameter to be a parameter array (Parameter arrays). このような関数メンバーは、適用可能な (適用可能な関数メンバー) に応じて、通常の形式または拡張された形式で呼び出されます。Such function members are invoked either in their normal form or in their expanded form depending on which is applicable (Applicable function member):

  • パラメーター配列を持つ関数メンバーが通常の形式で呼び出される場合、パラメーター配列に指定された引数は、暗黙的に変換可能な (暗黙の変換) 1 つの式である必要があります。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.
  • パラメーター配列を持つ関数メンバーが拡張された形式で呼び出される場合、呼び出しではパラメーター配列に0個以上の位置引数を指定する必要があります。各引数は、暗黙的に変換可能な式 (暗黙的な変換) で、パラメーター配列の要素型になります。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.

引数リストの式は、常に記述された順序で評価されます。The expressions of an argument list are always evaluated in the order they are written. この例では、Thus, the example

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++);
    }
}

この例では、次のように出力されます。produces the output

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

配列の相互分散規則 (配列の共変性) では、 A[] B[] からへの暗黙の参照変換が存在する場合、配列型の値を配列型のインスタンスへの参照にすることが許可され B A ます。The array co-variance rules (Array covariance) permit a value of an array type A[] to be a reference to an instance of an array type B[], provided an implicit reference conversion exists from B to A. これらの規則により、 reference_type の配列要素が参照パラメーターまたは出力パラメーターとして渡されるときに、配列の実際の要素型がパラメーターの要素の型と同じであることを確認するために、ランタイムチェックが必要になります。Because of these rules, when an array element of a reference_type is passed as a reference or output parameter, a run-time check is required to ensure that the actual element type of the array is identical to that of the parameter. この例では、In the example

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

の2番目の呼び出しでは FSystem.ArrayTypeMismatchException の実際の要素の型 b がではなく、がスローされ string object ます。the second invocation of F causes a System.ArrayTypeMismatchException to be thrown because the actual element type of b is string and not object.

パラメーター配列を持つ関数メンバーが拡張された形式で呼び出されると、配列初期化子 (配列作成式) を含む配列作成式が展開されたパラメーターの周囲に挿入された場合とまったく同じように、呼び出しが処理されます。When a function member with a parameter array is invoked in its expanded form, the invocation is processed exactly as if an array creation expression with an array initializer (Array creation expressions) was inserted around the expanded parameters. たとえば、次のように宣言したとします。For example, given the declaration

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

メソッドの拡張形式の次の呼び出しthe following invocations of the expanded form of the method

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

はに正確に対応します。correspond exactly to

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

特に、パラメーター配列に引数が指定されていない場合は、空の配列が作成されることに注意してください。In particular, note that an empty array is created when there are zero arguments given for the parameter array.

対応する省略可能なパラメーターを使用して関数メンバーから引数を省略すると、関数メンバー宣言の既定の引数が暗黙的に渡されます。When arguments are omitted from a function member with corresponding optional parameters, the default arguments of the function member declaration are implicitly passed. これらは常に定数であるため、他の引数の評価順序には影響しません。Because these are always constant, their evaluation will not impact the evaluation order of the remaining arguments.

型の推論Type inference

型引数を指定せずにジェネリックメソッドを呼び出すと、 型推論 プロセスは、その呼び出しの型引数を推論しようとします。When a generic method is called without specifying type arguments, a type inference process attempts to infer type arguments for the call. 型の推定が存在することにより、ジェネリックメソッドを呼び出すためにより便利な構文を使用できるようになり、冗長な型情報の指定を避けることができます。The presence of type inference allows a more convenient syntax to be used for calling a generic method, and allows the programmer to avoid specifying redundant type information. たとえば、次のようなメソッド宣言があるとします。For example, given the method declaration:

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

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

型引数を明示的に指定しなくても、メソッドを呼び出すことができ Choose ます。it is possible to invoke the Choose method without explicitly specifying a type argument:

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

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

型の推定を通じて、型引数 intstring は、メソッドの引数から決定されます。Through type inference, the type arguments int and string are determined from the arguments to the method.

型の推定は、メソッド呼び出し (メソッド呼び出し) のバインド時の処理の一部として発生し、呼び出しのオーバーロードの解決手順の前に実行されます。Type inference occurs as part of the binding-time processing of a method invocation (Method invocations) and takes place before the overload resolution step of the invocation. メソッドの呼び出しで特定のメソッドグループが指定され、メソッドの呼び出しの一部として型引数が指定されていない場合、メソッドグループの各ジェネリックメソッドに型の推定が適用されます。When a particular method group is specified in a method invocation, and no type arguments are specified as part of the method invocation, type inference is applied to each generic method in the method group. 型の推定が成功した場合は、推論される型引数を使用して、後続のオーバーロードの解決のための引数の型を決定します。If type inference succeeds, then the inferred type arguments are used to determine the types of arguments for subsequent overload resolution. オーバーロードの解決によって、呼び出し元としてジェネリックメソッドが選択された場合、推定される型引数が呼び出しの実際の型引数として使用されます。If overload resolution chooses a generic method as the one to invoke, then the inferred type arguments are used as the actual type arguments for the invocation. 特定のメソッドの型の推定が失敗した場合、そのメソッドはオーバーロードの解決に関与しません。If type inference for a particular method fails, that method does not participate in overload resolution. 型の推定の失敗は、それ自体のおよびでは、バインディング時エラーは発生しません。The failure of type inference, in and of itself, does not cause a binding-time error. ただし、オーバーロードの解決によって適用可能なメソッドが見つからない場合は、多くの場合、バインド時のエラーが発生します。However, it often leads to a binding-time error when overload resolution then fails to find any applicable methods.

指定された引数の数が、メソッドのパラメーターの数と異なる場合、推論はすぐに失敗します。If the supplied number of arguments is different than the number of parameters in the method, then inference immediately fails. それ以外の場合は、ジェネリックメソッドに次のシグネチャがあると仮定します。Otherwise, assume that the generic method has the following signature:

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

フォームのメソッド呼び出しでは、型の M(E1...Em) 推定のタスクが、呼び出しが有効になる S1...Sn ように、型パラメーターごとに一意の型引数を検索し X1...Xn M<S1...Sn>(E1...Em) ます。With a method call of the form M(E1...Em) the task of type inference is to find unique type arguments S1...Sn for each of the type parameters X1...Xn so that the call M<S1...Sn>(E1...Em) becomes valid.

推論プロセスでは、各型パラメーター Xi が特定の型に 固定 され Si ているか、または関連付けられている 境界 セットによっ 固定されていません。During the process of inference each type parameter Xi is either fixed to a particular type Si or unfixed with an associated set of bounds. 各境界は、何らかの型に T なります。Each of the bounds is some type T. 初期状態 Xi では、各型の変数は、空の境界セットでは修正されません。Initially each type variable Xi is unfixed with an empty set of bounds.

型の推定はフェーズで行われます。Type inference takes place in phases. 各フェーズでは、前のフェーズの結果に基づいて、より多くの型変数の型引数を推論しようとします。Each phase will try to infer type arguments for more type variables based on the findings of the previous phase. 最初のフェーズでは、境界の初期推論を行います。2番目のフェーズでは、型の変数を特定の型に修正し、さらに境界を推測します。The first phase makes some initial inferences of bounds, whereas the second phase fixes type variables to specific types and infers further bounds. 2番目のフェーズは、繰り返しが必要になる場合があります。The second phase may have to be repeated a number of times.

注: 型の推定は、ジェネリックメソッドが呼び出された場合にのみ行われます。Note: Type inference takes place not only when a generic method is called. メソッドグループの変換に対する型の推論については、「 メソッドグループの変換の型の推定 」で説明されています。また、式のセットの最適な共通型の検索については、「 式セットの最適な共通型の検索」で説明されています。Type inference for conversion of method groups is described in Type inference for conversion of method groups and finding the best common type of a set of expressions is described in Finding the best common type of a set of expressions.

最初のフェーズThe first phase

各メソッドの引数について、 Ei 次の手順を実行します。For each of the method arguments Ei:

  • Eiが匿名関数の場合は、明示的なパラメーター型の推論(明示的なパラメーター型の推論) がからに作成されます。 Ei``TiIf Ei is an anonymous function, an explicit parameter type inference (Explicit parameter type inferences) is made from Ei to Ti
  • それ以外の場合、に型があり、値パラメーターである場合、 Ei U xi から下限の推論 が行われ U Ti ます。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 xi がまたはパラメーターである場合、 ref out からへの 正確な 推論 が行われ U Ti ます。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.

2番目のフェーズThe second phase

2番目のフェーズは、次のように進行します。The second phase proceeds as follows:

  • Xi (依存関係)に依存 しないすべての非修正型変数 Xj は固定 (修正) されます。All unfixed type variables Xi which do not depend on (Dependence) any Xj are fixed (Fixing).
  • このような型の変数が存在しない場合は、すべての未修正 の型変数 Xi固定 され、次のすべてが保持されます。If no such type variables exist, all unfixed type variables Xi are fixed for which all of the following hold:
    • に依存する型変数が少なくとも1つあり 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 いますが、入力 の型 (入力型) には、から への 出力型の推論(出力型の推論) が行われ Ei Ti ます。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. 次に、2番目のフェーズが繰り返されます。Then the second phase is repeated.

入力の種類Input types

Eがメソッドグループまたは暗黙的に型指定された匿名関数であり、 T デリゲート型または式ツリー型である場合、のすべてのパラメーター型 T は型を持つの 入力型E T なります。If E is a method group or implicitly typed anonymous function and T is a delegate type or expression tree type then all the parameter types of T are input types of E with type T.

出力の種類Output types

Eがメソッドグループまたは匿名関数で、 T デリゲート型または式ツリー型である場合、の戻り値の型 T は型 のの出力型E T なります。If E is a method group or an anonymous function and T is a delegate type or expression tree type then the return type of T is an output type of E with type T.

依存Dependence

固定されていない 型の変数は、 型を持つ Xi Xj Ek Tk Xj入力型 に含まれる引数が型 Ek Tk XiEk Tk ある場合に、固定されていない型の変数に直接依存します。An unfixed type variable Xi depends directly on an unfixed type variable Xj if for some argument Ek with type Tk Xj occurs in an input type of Ek with type Tk and Xi occurs in an output type of Ek with type Tk.

Xj依存先 XiXj に直接依存 Xi しているか、がに Xi 直接依存 Xk しており、 Xk Xj 依存している場合。Xj depends on Xi if Xj depends directly on Xi or if Xi depends directly on Xk and Xk depends on Xj. したがって、"依存関係" は推移的ですが、"直接に依存している" の再帰クロージャではありません。Thus "depends on" is the transitive but not reflexive closure of "depends directly on".

出力の型の推論Output type inferences

出力型の推論 は、 E 次のように式から型 対して行われ T ます。An output type inference is made from an expression E to a type T in the following way:

  • が、推論された E 戻り値の型 (推定戻り値の型) を持つ匿名関数で、戻り値の U 型を T 持つデリゲート型または式ツリー型である場合は Tb 、下限の 推論(下限の推論) が から U なり Tb ます。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 1 つのメソッドが生成される場合は、 U から に対して 下限の推論 が行われ U Tb ます。Otherwise, if E is a method group and T is a delegate type or expression tree type with parameter types T1...Tk and return type Tb, and overload resolution of E with the types T1...Tk yields a single method with return type U, then a lower-bound inference is made from U to Tb.
  • それ以外の場合、 E が型の式である場合、 U から下限の推論 が行われ U T ます。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 次のように式から型 対して行われ T ます。An explicit parameter type inference is made from an expression E to a type T in the following way:

  • Eが、パラメーター型を持つ明示的に型指定された匿名関数であり、 U1...Uk T パラメーター型を持つデリゲート型または式ツリー型である場合は、に V1...Vk 対して Ui 正確な推論 が行われ Ui Vi ます。If E is an explicitly typed anonymous function with parameter types U1...Uk and T is a delegate type or expression tree type with parameter types V1...Vk then for each Ui an exact inference (Exact inferences) is made from Ui to the corresponding Vi.

正確な推論Exact inferences

から 型への正確な推論 U は、次のように V 行われます。An exact inference from a type U to a type V is made as follows:

  • 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...Vk U1...Uk 次のいずれかのケースが適用されるかどうかを確認することによって、とを設定しますOtherwise, sets V1...Vk and U1...Uk are determined by checking if any of the following cases apply:

    • V は配列型で V1[...]U U1[...] 同じ順位の配列型です。V is an array type V1[...] and U is an array type U1[...] of the same rank
    • V は型で V1?U は型です。 U1?V is the type V1? and U is the type U1?
    • V は構築された型であり、 C<V1...Vk> U 構築された型です C<U1...Uk>V is a constructed type C<V1...Vk>and U is a constructed type C<U1...Uk>

    これらのいずれかのケースに該当する場合は、それぞれの から 対応するに対して 正確な推論 が行われ Ui Vi ます。If any of these cases apply then an exact inference is made from each Ui to the corresponding Vi.

  • それ以外の場合、推論は行われません。Otherwise no inferences are made.

下限の推論Lower-bound inferences

から 型への下限の推論は、次のよう U V 行われます。A lower-bound inference from a type U to a type V is made as follows:

  • が固定されていないのいずれかである場合、 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? からへの下限の推論が行われ U1 V1 ます。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...Uk V1...Vk 次のいずれかのケースが適用されるかどうかを確認することによって、とを設定しますOtherwise, sets U1...Uk and V1...Vk are determined by checking if any of the following cases apply:

    • V は配列型で V1[...]U U1[...] 同じ順位の配列型 (または有効な基本型がである型パラメーター U1[...] ) ですV is an array type V1[...] and U is an array type U1[...] (or a type parameter whose effective base type is U1[...]) of the same rank

    • V が、、またはのいずれか IEnumerable<V1> で、 ICollection<V1> IList<V1> U 1 次元配列型 U1[] (または有効な基本型がである型パラメーター U1[] ) です。V is one of IEnumerable<V1>, ICollection<V1> or IList<V1> and U is a one-dimensional array type U1[](or a type parameter whose effective base type is U1[])

    • V は、構築されたクラス、構造体、インターフェイス、またはデリゲート型で、 C<V1...Vk> C<U1...Uk> U U が型パラメーターの場合、その有効な基底クラスまたはその有効なインターフェイスセットのメンバーがと同じであるか、(直接または間接的に) を継承するか、または (直接または間接的に) 実装することを示す一意の型です C<U1...Uk>V is a constructed class, struct, interface or delegate type C<V1...Vk> and there is a unique type C<U1...Uk> such that U (or, if U is a type parameter, its effective base class or any member of its effective interface set) is identical to, inherits from (directly or indirectly), or implements (directly or indirectly) C<U1...Uk>.

      "一意性" の制限は、ケースインターフェイスで、 C<T> {} class U: C<X>, C<Y> {} からへの推論時に推論が行われないことを意味し U C<T> ます。これは、またはである可能性があるため U1 X Y です。(The "uniqueness" restriction means that in the case interface C<T> {} class U: C<X>, C<Y> {}, then no inference is made when inferring from U to C<T> because U1 could be X or Y.)

    これらのいずれかのケースに該当する場合は、次 ように、それぞれのに対して推論が行われ Ui Vi ます。If any of these cases apply then an inference is made from each Ui to the corresponding Vi as follows:

    • Uiが参照型でないことがわかっている場合は、正確な推論 が行われます。If Ui is not known to be a reference type then an exact inference is made
    • それ以外の場合、が配列型である場合は、 U 下限の推論 が行われます。Otherwise, if U is an array type then a lower-bound inference is made
    • それ以外の場合、 V がの場合、 C<V1...Vk> 推論はの i 番目の型パラメーターに依存し C ます。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

から 型への上限の推論 U は、 V 次のように行われます。An upper-bound inference from a type U to a type V is made as follows:

  • が固定され 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...Vk U1...Uk 次のいずれかのケースが適用されるかどうかを確認することによって、とを設定しますOtherwise, sets V1...Vk and U1...Uk are determined by checking if any of the following cases apply:

    • U は配列型で U1[...]V V1[...] 同じ順位の配列型です。U is an array type U1[...] and V is an array type V1[...] of the same rank

    • U が、、またはのいずれかで IEnumerable<Ue> 、が ICollection<Ue> IList<Ue> V 1 次元配列型です。 Ve[]U is one of IEnumerable<Ue>, ICollection<Ue> or IList<Ue> and V is a one-dimensional array type Ve[]

    • U は型で U1?V は型です。 V1?U is the type U1? and V is the type V1?

    • U は、構築されたクラス、構造体、インターフェイス、またはデリゲート型で、 C<U1...Uk>V 同一のクラス、構造体、インターフェイス、またはデリゲート型であり、(直接または間接的に) を継承しているか、または一意の型を (直接または間接的に) 実装しています C<V1...Vk>U is constructed class, struct, interface or delegate type C<U1...Uk> and V is a class, struct, interface or delegate type which is identical to, inherits from (directly or indirectly), or implements (directly or indirectly) a unique type C<V1...Vk>

      ("一意性" の制限は、を持っている場合 interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{} 、からへの推論で推論が行われないことを意味し C<U1> V<Q> ます。(The "uniqueness" restriction means that if we have interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}, then no inference is made when inferring from C<U1> to V<Q>. 推論は、からまたはに対して行われません U1 X<Q> Y<Q> )。Inferences are not made from U1 to either X<Q> or Y<Q>.)

    これらのいずれかのケースに該当する場合は、次 ように、それぞれのに対して推論が行われ Ui Vi ます。If any of these cases apply then an inference is made from each Ui to the corresponding Vi as follows:

    • Uiが参照型でないことがわかっている場合は、正確な推論 が行われます。If Ui is not known to be a reference type then an exact inference is made
    • それ以外の場合、が配列型であれば、 V 上限の推論 が行われます。Otherwise, if V is an array type then an upper-bound inference is made
    • それ以外の場合、 U がの場合、 C<U1...Uk> 推論はの i 番目の型パラメーターに依存し C ます。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

Xi 範囲のセットを持つ固定されていない型変数は、次のように 修正 されます。An unfixed type variable Xi with a set of bounds is fixed as follows:

  • 候補の種類 のセットは、の一連の Uj 境界内のすべての型のセットとして開始され Xi ます。The set of candidate types Uj starts out as the set of all types in the set of bounds for Xi.
  • 次に、各バインドを Xi 順番に検証します。 U 一致し Xi ていないすべての型の完全バインド 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. からの暗黙的な U Xi 変換がないすべての型の下限 Uj U は、候補セットから削除されます。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. U Xi 暗黙の型変換が行われていないすべての型の上限 Uj 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 はに固定され V ます。If 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 は、型の推定およびオーバーロードの解決の際に使用されます。The inferred return type of an anonymous function F is used during type inference and overload resolution. 推論された戻り値の型は、すべてのパラメーター型が明示的に指定されている場合にのみ、匿名関数の変換によって指定されるか、または外側のジェネリックメソッドの呼び出しで型の推論中に推論されるため、すべてのパラメーター型がわかっている場合にのみ決定できます。The inferred return type can only be determined for an anonymous function where all parameter types are known, either because they are explicitly given, provided through an anonymous function conversion or inferred during type inference on an enclosing generic method invocation.

推論される 結果の型 は、次のように決定されます。The inferred result type is determined as follows:

  • の本体 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 (一連の 式の中で最適な共通型を見つける) を持つ場合、の推定結果型はに F T なります。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.
  • それ以外の場合、の結果型を推論することはできません FOtherwise, a result type cannot be inferred for F.

推論される 戻り値の型 は、次のように決定されます。The inferred return type is determined as follows:

  • Fが async で、の本体 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 、推論される戻り値の型は T です。If F is non-async and has an inferred result type T, the inferred return type is T.
  • それ以外の場合、の戻り値の型を推論することはできません FOtherwise a return type cannot be inferred for F.

匿名関数を含む型の推定の例として、クラスで宣言された拡張メソッドを考えてみ Select System.Linq.Enumerable ます。As an example of type inference involving anonymous functions, consider the Select extension method declared in the System.Linq.Enumerable class:

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);
        }
    }
}

System.Linq名前空間が句を使用してインポートされ、型のプロパティを持つクラスがあると仮定した using Customer Name string 場合、メソッドを使用して Select 顧客の一覧の名前を選択できます。Assuming the System.Linq namespace was imported with a using clause, and given a class Customer with a Name property of type string, the Select method can be used to select the names of a list of customers:

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

の拡張メソッドの呼び出し (拡張メソッドの呼び出し) Select は、静的メソッドの呼び出しへの呼び出しをリライトすることによって処理されます。The extension method invocation (Extension method invocations) of Select is processed by rewriting the invocation to a static method invocation:

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

型引数が明示的に指定されていないため、型引数を推論するために型の推定が使用されます。Since type arguments were not explicitly specified, type inference is used to infer the type arguments. 最初に、 customers 引数はパラメーターに関連付けられ source 、として推論 T され Customer ます。First, the customers argument is related to the source parameter, inferring T to be Customer. 次に、上記で説明した匿名関数型推論プロセスを使用して、 cCustomer を指定し c.Name ます。式は、パラメーターの戻り値の型に関連付けられ selector 、として推論され S string ます。Then, using the anonymous function type inference process described above, c is given type Customer, and the expression c.Name is related to the return type of the selector parameter, inferring S to be string. したがって、呼び出しはと同じです。Thus, the invocation is equivalent to

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

結果は型になり IEnumerable<string> ます。and the result is of type IEnumerable<string>.

次の例では、匿名関数型推論によって、ジェネリックメソッド呼び出しの引数間で型情報を "flow" できるようにする方法を示します。The following example demonstrates how anonymous function type inference allows type information to "flow" between arguments in a generic method invocation. 次のメソッドを指定します。Given the method:

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

呼び出しの型の推定:Type inference for the invocation:

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

次のように処理を進めます。最初に、引数 "1:15:30" がパラメーターに関連付けられ value 、として推論 X され string ます。proceeds as follows: First, the argument "1:15:30" is related to the value parameter, inferring X to be string. 次に、最初の匿名関数のパラメーターには、推論された型が指定され、 s string 式は TimeSpan.Parse(s) の戻り値の型に関連付けられ、として推論され f1 Y System.TimeSpan ます。Then, the parameter of the first anonymous function, s, is given the inferred type string, and the expression TimeSpan.Parse(s) is related to the return type of f1, inferring Y to be System.TimeSpan. 最後に、2番目の匿名関数のパラメーターには、推論された型が指定され、 t System.TimeSpan 式は t.TotalSeconds の戻り値の型に関連付けられ、として推論され f2 Z double ます。Finally, the parameter of the second anonymous function, t, is given the inferred type System.TimeSpan, and the expression t.TotalSeconds is related to the return type of f2, inferring Z to be double. したがって、呼び出しの結果は型になり double ます。Thus, the result of the invocation is of type double.

メソッドグループの変換の型推論Type inference for conversion of method groups

ジェネリックメソッドの呼び出しと同様に、ジェネリックメソッドを含むメソッドグループを M 特定のデリゲート型 D (メソッドグループ変換) に変換する場合は、型の推定も適用する必要があります。Similar to calls of generic methods, type inference must also be applied when a method group M containing a generic method is converted to a given delegate type D (Method group conversions). 指定されたメソッドGiven a method

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

また、 M デリゲート型に割り当てられているメソッドグループは、型引数を検索して式を指定し D S1...Sn ます。and the method group M being assigned to the delegate type D the task of type inference is to find type arguments S1...Sn so that the expression:

M<S1...Sn>

はと互換性があります (デリゲート宣言) Dbecomes compatible (Delegate declarations) with D.

ジェネリックメソッド呼び出しの型推論アルゴリズムとは異なり、この例では引数の のみが存在し、引数の はありません。Unlike the type inference algorithm for generic method calls, in this case there are only argument types, no argument expressions. 特に、匿名関数は存在しないため、推論の複数のフェーズを行う必要はありません。In particular, there are no anonymous functions and hence no need for multiple phases of inference.

代わりに、すべて Xi が未 修正と 見なされ、の各引数の型 から Uj D の対応するパラメーターの型 下限の推論が行われ Tj M ます。Instead, all Xi are considered unfixed, and a lower-bound inference is made from each argument type Uj of D to the corresponding parameter type Tj of M. いずれかの境界が Xi 見つからなかった場合、型の推定は失敗します。If for any of the Xi no bounds were found, type inference fails. それ以外の場合、すべて Xi が対応するに 固定 され Si ます。これは、型の推定の結果です。Otherwise, all Xi are fixed to corresponding Si, which are the result of type inference.

一連の式の中で最もよく使われる型の検索Finding the best common type of a set of expressions

場合によっては、一連の式に対して共通の型を推論する必要があります。In some cases, a common type needs to be inferred for a set of expressions. 特に、暗黙的に型指定された配列の要素型と ブロック 本体を持つ匿名関数の戻り値の型は、この方法で見つかります。In particular, the element types of implicitly typed arrays and the return types of anonymous functions with block bodies are found in this way.

直感的に言えば、一連の式を指定すると、 E1...Em この推論はメソッドを呼び出すのと同じになります。Intuitively, given a set of expressions E1...Em this inference should be equivalent to calling a method

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

Ei 引数として使用します。with the Ei as arguments.

より正確には、固定されてい ない型変数を使用 して推論が開始され X ます。More precisely, the inference starts out with an unfixed type variable X. 次に、それぞれ のからへの**出力の型の推論 が行われ Ei X ます。Output type inferences are then made from each Ei to X. 最後に、 X固定 されています。成功した場合、結果の型 S は式に対して生成される最適な共通型になります。Finally, X is fixed and, if successful, the resulting type S is the resulting best common type for the expressions. 存在しない場合 S 、式には最適な共通型がありません。If no such S exists, the expressions have no best common type.

オーバーロードの解決Overload resolution

オーバーロードの解決は、引数リストと候補となる関数メンバーのセットを呼び出すための最適な関数メンバーを選択するためのバインディング時の機構です。Overload resolution is a binding-time mechanism for selecting the best function member to invoke given an argument list and a set of candidate function members. オーバーロードの解決では、C# 内の次の異なるコンテキストで呼び出す関数メンバーを選択します。Overload resolution selects the function member to invoke in the following distinct contexts within C#:

これらの各コンテキストでは、上記のセクションで詳しく説明したように、候補となる関数メンバーのセットと引数のリストが独自の一意の方法で定義されています。Each of these contexts defines the set of candidate function members and the list of arguments in its own unique way, as described in detail in the sections listed above. たとえば、メソッド呼び出しの候補のセットには、(メンバー検索) とマークされたメソッドは含まれません override 。派生クラスのメソッドが適用可能な場合 (メソッド呼び出し)、基底クラスのメソッドは候補になりません。For example, the set of candidates for a method invocation does not include methods marked override (Member lookup), and methods in a base class are not candidates if any method in a derived class is applicable (Method invocations).

候補の関数メンバーと引数リストが識別されると、最適な関数メンバーの選択は常に同じになります。Once the candidate function members and the argument list have been identified, the selection of the best function member is the same in all cases:

  • 適用候補の関数メンバーのセットが見つかった場合、そのセット内の最適な関数メンバーが配置されます。Given the set of applicable candidate function members, the best function member in that set is located. セットに含まれる関数メンバーが1つだけの場合は、その関数メンバーが最適な関数メンバーになります。If the set contains only one function member, then that function member is the best function member. それ以外の場合、最適な関数メンバーは、指定された引数リストに対する他のすべての関数メンバーと比較して適切な1つの関数メンバーになります。つまり、各関数メンバーは、 より優れた関数メンバーの規則を使用して他のすべての関数メンバーと比較されます。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. 他のすべての関数メンバーよりも適切な関数メンバーが1つしかない場合は、関数メンバー呼び出しがあいまいになり、バインディング時エラーが発生します。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.

以下のセクションでは、*該当する関数メンバー _ および _ より優れた関数メンバー * という用語の正確な意味を定義します。The following sections define the exact meanings of the terms applicable function member _ and _better function member**.

適用可能な関数メンバーApplicable function member

関数メンバーは、次のすべてに該当する場合に、引数リストに対して 適用可能な関数メンバー と呼ばれ A ます。A function member is said to be an applicable function member with respect to an argument list A when all of the following are true:

  • の各引数 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 、引数のパラメーター渡しモード (つまり、値、 ref 、または out ) は、対応するパラメーターのパラメーター渡しモードと同じになります。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
    • refパラメーターまたは out パラメーターの場合、引数の型は対応するパラメーターの型と同じになります。for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter. 結局のところ、 ref パラメーターまたはパラメーターは渡された out 引数のエイリアスです。After all, a ref or out parameter is an alias for the argument passed.

パラメーター配列を含む関数メンバーでは、関数メンバーが上記の規則によって適用される場合、その関数メンバーは *標準形式 _ で適用されると言います。For a function member that includes a parameter array, if the function member is applicable by the above rules, it is said to be applicable in its *normal form _. パラメーター配列を含む関数メンバーを通常の形式で適用できない場合は、その関数メンバーを _ 展開形式 * で適用できます。If a function member that includes a parameter array is not applicable in its normal form, the function member may instead be applicable in its _*expanded form**:

  • 展開されたフォームを作成するには、関数メンバー宣言のパラメーター配列を、パラメーター配列の要素型の0個以上の値パラメーターに置き換えます。これにより、引数リスト内の引数の数が 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
    • refパラメーターまたは out パラメーターの場合、引数の型は対応するパラメーターの型と同じになります。for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter.

より優れた関数メンバーBetter function member

より優れた関数メンバーを決定するために、削除された引数リストは、元の引数リストに出現する順序で引数式だけを含むように構築されます。For the purposes of determining the better function member, a stripped-down argument list A is constructed containing just the argument expressions themselves in the order they appear in the original argument list.

各候補関数メンバーのパラメーターリストは、次のように構築されます。Parameter lists for each of the candidate function members are constructed in the following way:

  • 拡張されたフォームは、関数メンバーが展開されたフォームでのみ適用された場合に使用されます。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.

引数 A の式のセットと2つの適用可能な関数メンバー、およびパラメーターの型とを持つ引数リストを指定した {E1, E2, ..., En} Mp Mq 場合、は次のよう {P1, P2, ..., Pn} {Q1, Q2, ..., Qn} Mp により 優れた関数メンバー として定義 Mq されます。Given an argument list A with a set of argument expressions {E1, E2, ..., En} and two applicable function members Mp and Mq with parameter types {P1, P2, ..., Pn} and {Q1, Q2, ..., Qn}, Mp is defined to be a better function member than Mq if

  • 引数ごとに、からへの暗黙の型変換 Ex Qx は、からへの暗黙的な変換よりも適切ではありません。 Ex Pxfor each argument, the implicit conversion from Ex to Qx is not better than the implicit conversion from Ex to Px, and
  • 少なくとも1つの引数に対してからへの変換は、 Ex Px からへの変換よりも優れてい Ex Qx ます。for at least one argument, the conversion from Ex to Px is better than the conversion from Ex to Qx.

この評価を実行する場合、 Mp または Mq が展開された形式で適用される場合、 Px またはは Qx パラメーターリストの拡張された形式のパラメーターを参照します。When performing this evaluation, if Mp or Mq is applicable in its expanded form, then Px or Qx refers to a parameter in the expanded form of the parameter list.

パラメーターの型のシーケンス  {P1, P2, ..., Pn} とが等価である場合 {Q1, Q2, ..., Qn} (つまり Pi 、それぞれに対応するに id が変換されている場合 Qi )、より適切な関数メンバーを決定するために、次の相互に一致する規則が順番に適用されます。In case the parameter type sequences {P1, P2, ..., Pn} and {Q1, Q2, ..., Qn} are equivalent (i.e. each Pi has an identity conversion to the corresponding Qi), the following tie-breaking rules are applied, in order, to determine the better function member.

  • Mpが非ジェネリックメソッドで、ジェネリックメソッドである場合 MqMp はよりも優れてい Mq ます。If Mp is a non-generic method and Mq is a generic method, then Mp is better than Mq.
  • それ以外の場合、 Mp が通常の形式で適用可能で Mq あり、配列を持ち、 params 拡張された形式でのみ適用できる場合は、 Mp よりも優れてい Mq ます。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 Mp はよりも優れてい Mq ます。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 対応する引数を指定し、既定の引数をの少なくとも1つの省略可能なパラメーターに置き換える必要があり Mq Mp Mq ます。Otherwise if all parameters of Mp have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in Mq then Mp is better than Mq.
  • それ以外の場合、が Mp よりも固有のパラメーター型を持つ場合 Mq Mp は、よりも優れてい Mq ます。Otherwise, if Mp has more specific parameter types than Mq, then Mp is better than Mq. とを使用して、と {R1, R2, ..., Rn} {S1, S2, ..., Sn} のインスタンスおよび展開されていないパラメーターの型を表し Mp Mq ます。Let {R1, R2, ..., Rn} and {S1, S2, ..., Sn} represent the uninstantiated and unexpanded parameter types of Mp and Mq. Mpのパラメーターの型は、 Mq 各パラメーターについてよりも具体的で Rx あり、よりも限定的ではなく Sx 、少なくとも1つのパラメーターについて Rx はより固有です SxMp'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.
    • 1つ以上の型引数がより限定的で、型引数がもう一方の型引数よりも限定的でない場合、構築された型は再帰的に (型引数の数が同じである) 別の構築型よりも固有になります。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.
    • 配列型は、1つ目の要素の型が2番目の要素の型よりも固有である場合、(次元数が同じ) 別の配列型よりも具体的です。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.
  • それ以外の場合、一方のメンバーがリフトされていない演算子で、もう一方がリフトされた演算子の場合、リフトされていない1つの方が適しています。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.

式からの変換の向上Better conversion from expression

式から型に変換する暗黙的な変換 C1 E と、 T1 C2 式から型に変換する暗黙的な変換 E T2 C1 は、が完全に一致せず、 C2 E T2 少なくとも次のいずれかのが一致しない場合よりも、変換がより適切です。Given an implicit conversion C1 that converts from an expression E to a type T1, and an implicit conversion C2 that converts from an expression E to a type T2, C1 is a better conversion than C2 if E does not exactly match T2 and at least one of the following holds:

正確に一致する式Exactly matching Expression

式と型が指定され ET E T いる場合、次のいずれかがを保持すると、厳密に一致します。Given an expression E and a type T, E exactly matches T if one of the following holds:

  • Eに型があり S 、からへの id 変換が存在します。 S``TE has a type S, and an identity conversion exists from S to T
  • E は匿名関数であり、 T デリゲート型または式ツリー型のいずれかで、 D Expression<D> 次のいずれかが保持されます。E is an anonymous function, T is either a delegate type D or an expression tree type Expression<D> and one of the following holds:
    • 推論された戻り値の型が X E のパラメーターリストのコンテキスト D (推定戻り値の型) に存在し、から X の戻り値の型への id 変換が存在します。 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 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

2つの異なる型とが指定されて T1 T2 T1 T2 いる場合、からへの暗黙的な変換が存在せず、 T2 T1 少なくとも次のいずれかのが保持されている場合よりも、変換ターゲットは向上します。Given two different types T1 and T2, T1 is a better conversion target than T2 if no implicit conversion from T2 to T1 exists, and at least one of the following holds:

  • からへの暗黙の型変換 T1 T2An 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 void を返すD2 is void returning
    • D2 に戻り値の型があり S2S1 より適切な変換ターゲットである S2D2 has a return type S2, and S1 is a better conversion target than S2
  • T1Task<S1> で、 T2Task<S2> で、が S1 より適切な変換ターゲットです。 S2T1 is Task<S1>, T2 is Task<S2>, and S1 is a better conversion target than S2
  • T1 がであるか、が S1 S1? S1 符号付き整数型であり、 T2 がであるか、またはが S2 S2? 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 S2 で、が byte 、、 ushort uint 、またはです。 ulongS1 is sbyte and S2 is byte, ushort, uint, or ulong
    • S1short S2 で、が ushort 、、 uint またはです。 ulongS1 is short and S2 is ushort, uint, or ulong
    • S1intS2 uint 、がであるか、または ulongS1 is int and S2 is uint, or ulong
    • S1 がで longS2 がです。 ulongS1 is long and S2 is ulong

オーバーロード (ジェネリッククラスでの)Overloading in generic classes

宣言されたシグネチャは一意である必要がありますが、型引数の代入によって同じシグネチャが生成される可能性があります。While signatures as declared must be unique, it is possible that substitution of type arguments results in identical signatures. このような場合、上記のオーバーロードの解決規則によって、最も限定的なメンバーが選択されます。In such cases, the tie-breaking rules of overload resolution above will pick the most specific member.

次の例は、この規則に従って有効で無効なオーバーロードを示しています。The following examples show overloads that are valid and invalid according to this rule:

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

動的にバインドされたほとんどの操作では、コンパイル時に解決できる候補のセットは不明です。For most dynamically bound operations the set of possible candidates for resolution is unknown at compile-time. ただし、場合によっては、候補セットはコンパイル時に認識されます。In certain cases, however the candidate set is known at compile-time:

  • 動的引数を使用した静的メソッド呼び出し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

このような場合、実行時に適用される可能性があるかどうかを確認するために、各候補に対して限定的なコンパイル時チェックが実行されます。この確認は、次の手順で構成されています。In these cases a limited compile-time check is performed for each candidate to see if any of them could possibly apply at run-time.This check consists of the following steps:

  • 部分型推論: 型の引数に直接または間接的に依存しない型引数 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

ここでは、特定の関数メンバーを呼び出すために実行時に実行されるプロセスについて説明します。This section describes the process that takes place at run-time to invoke a particular function member. バインド時のプロセスでは、呼び出される特定のメンバーが既に決定されていることを前提としています。これは、候補となる関数メンバーのセットにオーバーロードの解決を適用することによって行われる可能性があります。It is assumed that a binding-time process has already determined the particular member to invoke, possibly by applying overload resolution to a set of candidate function members.

呼び出しプロセスを記述する目的で、関数メンバーは次の2つのカテゴリに分類されます。For purposes of describing the invocation process, function members are divided into two categories:

  • 静的関数のメンバー。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 ます。ここで、は関数メンバーであり、 M がインスタンスメンバーである場合、 E はインスタンス式です。The run-time processing of a function member invocation consists of the following steps, where M is the function member and, if M is an instance member, E is the instance expression:

  • Mが静的関数メンバーである場合は、次のようになります。If M is a static function member:

    • 引数リストは、「 引数リスト」で説明されているように評価されます。The argument list is evaluated as described in Argument lists.
    • M が呼び出されます。M is invoked.
  • Mvalue_type で宣言されたインスタンス関数メンバーの場合は、次のようになります。If M is an instance function member declared in a value_type:

    • E が評価されます。E 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. 一時変数は、内でアクセスでき this M ますが、他の方法ではアクセスできません。The temporary variable is accessible as this within M, but not in any other way. したがって、が true に設定されている場合にのみ、 E 呼び出し元はに加えられた変更を確認でき M this ます。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.
    • M が呼び出されます。M is invoked. によって参照される変数は、 E によって参照される変数になり this ます。The variable referenced by E becomes the variable referenced by this.
  • Mreference_type で宣言されたインスタンス関数メンバーの場合は、次のようになります。If M is an instance function member declared in a reference_type:

    • E が評価されます。E is evaluated. この評価によって例外が発生した場合、それ以上の手順は実行されません。If this evaluation causes an exception, then no further steps are executed.
    • 引数リストは、「 引数リスト」で説明されているように評価されます。The argument list is evaluated as described in Argument lists.
    • の型 Evalue_type の場合、型に変換するボックス変換 (ボックス化変換) が実行され、 E 次の object E 手順では型と見なされ object ます。If the type of E is a value_type, a boxing conversion (Boxing conversions) is performed to convert E to type object, and E is considered to be of type object in the following steps. この場合、は M のメンバーである必要があり System.Object ます。In this case, M could only be a member of System.Object.
    • の値 E が有効であるかどうかがチェックされます。The value of E is checked to be valid. の値がの場合は、が E null スローされ、 System.NullReferenceException それ以上の手順は実行されません。If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.
    • 呼び出す関数メンバーの実装は、次のように決定されます。The function member implementation to invoke is determined:
      • のバインド時の型がインターフェイスである場合 E 、呼び出す関数メンバーは、 M によって参照されるインスタンスのランタイム型によって提供されるの実装です EIf 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. この関数メンバーは、 M によって参照されるインスタンスのランタイム型によって提供されるの実装を決定するために、インターフェイスマッピング規則 (インターフェイスマッピング) を適用することによって決定され E ます。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 が仮想関数メンバーである場合、呼び出す関数メンバーは、 M によって参照されるインスタンスのランタイム型によって提供されるの実装です EOtherwise, if M is a virtual function member, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. この関数メンバーは、によって参照されるインスタンスの実行時の型に関して、の最も派生された実装 (仮想メソッド) を決定するための規則を適用することによって決定され M E ます。This function member is determined by applying the rules for determining the most derived implementation (Virtual methods) of M with respect to the run-time type of the instance referenced by E.
      • それ以外の場合、 M は非仮想関数メンバーであり、呼び出す関数メンバー自体はです MOtherwise, 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:

  • 関数メンバーが override 型から継承されたメソッドので、 object 型のインスタンス式によって呼び出された場合 objectWhen 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.

このような場合、ボックス化されたインスタンスには value_type の変数が含まれていると見なされ、この変数は関数メンバー呼び出し内で参照される変数になり this ます。In these situations, the boxed instance is considered to contain a variable of the value_type, and this variable becomes the variable referenced by this within the function member invocation. これは特に、ボックス化されたインスタンスで関数メンバーが呼び出されたときに、関数メンバーがボックス化されたインスタンスに含まれる値を変更できることを意味します。In particular, this means that when a function member is invoked on a boxed instance, it is possible for the function member to modify the value contained in the boxed instance.

基本式Primary expressions

主な式には、最も単純な形式の式が含まれます。Primary expressions include the simplest forms of 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
    ;

プライマリ式は array_creation_expression s と primary_no_array_creation_expression の間で分けられます。Primary expressions are divided between array_creation_expression s and primary_no_array_creation_expression s. この方法で配列作成式を扱うことは、他の単純な式フォームと共にリストするのではなく、文法によって、次のような混乱の可能性のあるコードを許可しないようにします。Treating array-creation-expression in this way, rather than listing it along with the other simple expression forms, enables the grammar to disallow potentially confusing code such as

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

これは、which would otherwise be interpreted as

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

リテラルLiterals

リテラル(リテラル) で構成される primary_expression は、値として分類されます。A primary_expression that consists of a literal (Literals) is classified as a value.

挿入文字列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)+
    ;

補間内の constant_expression には、への暗黙の型変換が必要 int です。The constant_expression in an interpolation must have an implicit conversion to int.

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. それ以外の場合は、型 string です。Otherwise, it has the type string.

挿入文字列の型が System.IFormattable またはの場合 System.FormattableString 、はを呼び出し System.Runtime.CompilerServices.FormattableStringFactory.Create ます。If the type of an interpolated string is System.IFormattable or System.FormattableString, the meaning is a call to System.Runtime.CompilerServices.FormattableStringFactory.Create. 型がの場合 string 、式の意味はへの呼び出しに string.Format なります。If the type is string, the meaning of the expression is a call to string.Format. どちらの場合も、呼び出しの引数リストは、各補間のプレースホルダーを含む書式指定文字列リテラルと、プレースホルダーに対応する各式の引数で構成されます。In both cases, the argument list of the call consists of a format string literal with placeholders for each interpolation, and an argument for each expression corresponding to the place holders.

書式文字列リテラルは次のように構成され N ます。ここで、は interpolated_string_expression 内の補間の数です。The format string literal is constructed as follows, where N is the number of interpolations in the interpolated_string_expression:

  • Interpolated_regular_string_whole または interpolated_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_start または interpolated_verbatim_string_startFirst the interpolated_regular_string_start or interpolated_verbatim_string_start
    • 次に、からまでの各数値を指定し I 0 N-1 ます。Then for each number I from 0 to N-1:
      • の10進数表現 IThe decimal representation of I
      • 次に、対応する 補間constant_expression がある場合は、 , (コンマ) の後に constant_expression 、の値の10進数表現を続けます。Then, 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_mid 、または interpolated_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.

後続の引数は、単に 補間(存在する場合) からの です。The subsequent arguments are simply the expressions from the interpolations (if any), in order.

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_list です。A 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 0 にすることを検討してください。When no type_argument_list is specified, consider K to be zero. Simple_name が評価され、次のように分類されます。The simple_name is evaluated and classified as follows:

  • Kが0で、ブロック内に 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が0で、 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.
    • それ以外の場合、型引数を持つ in のメンバー参照 (メンバー参照) に I T よって K   一致が生成されます。Otherwise, if a member lookup (Member lookup) of I in T with K type arguments produces a match:
      • Tが、すぐ外側のクラスまたは構造体型のインスタンス型であり、参照が1つ以上のメソッドを識別する場合、結果は、のインスタンス式が関連付けられたメソッドグループになり 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 は、が0の場合にのみ発生します。This can only happen when K is zero.
      • それ以外の場合、結果は、またはの形式のメンバーアクセス (メンバーアクセス) と同じになり T.I T.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が0で、 I が内の名前空間の名前である場合は、次のようになり  N ます。If K is zero and I is the name of a namespace in N, then:
      • Simple_name が発生した場所がの名前空間宣言で囲まれていて、名前空間 N または型に名前を関連付ける extern_alias_directive または using_alias_directive が名前空間宣言に含まれている場合  Isimple_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 はで指定された名前空間を参照し I N ます。Otherwise, the simple_name refers to the namespace named I in N.
    • それ以外の場合、に N 名前と型パラメーターを持つアクセス可能な型が含まれている場合は、次  I K   のようになります。Otherwise, if N contains an accessible type having name I and K type parameters, then:
      • Kが0で、 simple_name が発生した場所がの名前空間宣言によって囲まれていて、名前空間 N または型に名前を関連付ける extern_alias_directive または using_alias_directive が名前空間宣言に含まれている場合  Isimple_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:
      • が0で、名前空間の宣言に、インポートされた名前 K 空間または型に名前を関連付ける extern_alias_directive または using_alias_directive が含まれている場合  Isimple_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_directive s および名前空間宣言の using_static_directive によってインポートされた名前空間と型の宣言に、名前と型のパラメーターを持つアクセス可能な型または非拡張静的メンバーが1つだけ含まれる場合、  I K   simple_name は、指定した型引数を使用して構築されたその型またはメンバーを参照します。Otherwise, if the namespaces and type declarations imported by the using_namespace_directive s and using_static_directive s 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_directive s によってインポートされた名前空間と型に、名前と型のパラメーターを持つアクセス可能な型または非拡張メソッドの静的メンバーが複数含まれている  I と、 K   simple_name があいまいになり、エラーが発生します。Otherwise, if the namespaces and types imported by the using_namespace_directive s 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 ')'
    ;

Parenthesized_expression は、かっこ内の を評価することによって評価されます。A parenthesized_expression is evaluated by evaluating the expression within the parentheses. かっこ内の が名前空間または型を表している場合は、コンパイル時エラーが発生します。If the expression within the parentheses denotes a namespace or type, a compile-time error occurs. それ以外の場合、 parenthesized_expression の結果は、含まれている を評価した結果になります。Otherwise, the result of the parenthesized_expression is the result of the evaluation of the contained expression.

メンバー アクセス。Member access

Member_access は、 primary_expressionpredefined_type、または qualified_alias_member で構成され、その後に "" トークンの後に識別子が続き、その後に、 . 必要に応じて type_argument_list が続きます。 A 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_list です。A 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 0 にすることを検討してください。When no type_argument_list is specified, consider K to be zero.

型の primary_expression を持つ member_access dynamic は動的にバインドされます (動的バインド)。A member_access with a primary_expression of type dynamic is dynamically bound (Dynamic binding). この場合、コンパイラはメンバーアクセスを型のプロパティアクセスとして分類し dynamic ます。In this case the compiler classifies the member access as a property access of type dynamic. 次の規則は、 member_access の意味を判断するために、 primary_expression のコンパイル時の型ではなく、実行時の型を使用して実行時に適用されます。The rules below to determine the meaning of the member_access are then applied at run-time, using the run-time type instead of the compile-time type of the primary_expression. この実行時の分類によってメソッドグループが発生する場合は、メンバーアクセスが invocation_expressionprimary_expression である必要があります。If this run-time classification leads to a method group, then the member access must be the primary_expression of an invocation_expression.

Member_access が評価され、次のように分類されます。The member_access is evaluated and classified as follows:

  • が0で、名前空間であり、 K E 名前が E の入れ子になった名前空間が含まれている場合、  I 結果はその名前空間になります。If K is zero and E is a namespace and E contains a nested namespace with name I, then the result is that namespace.
  • それ以外の場合、 E が名前空間であり、 E 名前と型パラメーターを持つアクセス可能な型が含まれている場合、  I 結果は指定された K   型引数を使用して構築された型になります。Otherwise, if E is a namespace and E contains an accessible type having name I and K type parameters, then the result is that type constructed with the given type arguments.
  • Eが型として分類された predefined_type または primary_expression の場合、 E が型パラメーターではなく、が型パラメーターを持つのメンバー参照 (メンバー参照) に I よって一致が E K   生成されると、は次のように E.I 評価され、分類されます。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 1 つ以上のメソッドを識別する場合、結果はインスタンス式が関連付けられていないメソッドグループになります。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 クラスまたは構造体の静的コンストラクターの外側で参照が発生した場合、結果はの値 (つまり、の静的フィールドの値) になり  I  E ます。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.
      • それ以外の場合、結果は変数 (つまり、の静的フィールド) になり  I  E ます。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 型引数を持つのメンバー参照 (メンバー参照) が一致を生成する場合、は次のように I T K   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 1 つ以上のメソッドを識別する場合、結果は、のインスタンス式が関連付けられたメソッドグループになり 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 this 、は I 自動的に実装されるプロパティ (自動的に実装されるプロパティ) を 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:
      • の値がの場合は、が E null System.NullReferenceException スローされます。If the value of E is null, then a System.NullReferenceException is thrown.
      • それ以外の場合、フィールドがで、その readonly フィールドが宣言されているクラスのインスタンスコンストラクターの外側で参照が発生した場合、結果は値になり  I ます。つまり、によって参照されるオブジェクトのフィールドの値です  EOtherwise, 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.
      • それ以外の場合、結果は変数、つまり  I によって参照されるオブジェクト内のフィールドになり  E ます。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 構造体のインスタンスコンストラクターの外側で参照が発生した場合、結果は値になり  I ます。つまり、によって指定された構造体のインスタンスコンストラクターの外で参照が発生し  E ます。If E is a value, or if the field is readonly and the reference occurs outside an instance constructor of the struct in which the field is declared, then the result is a value, namely the value of the field I in the struct instance given by E.
      • それ以外の場合、結果は変数、つまり  I によって指定された構造体インスタンス内のフィールドになり  E ます。Otherwise, the result is a variable, namely the field I in the struct instance given by E.
    • I インスタンスイベントを識別する場合:If I identifies an instance event:
      • イベントが宣言されているクラスまたは構造体の中で参照が発生し、イベントが event_accessor_declarations (イベント) なしで宣言されていて、その参照が or 演算子の左辺として発生していない場合、はが += -= 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

フォームのメンバーアクセスで E.IE が単一の識別子であり、が E simple_name (簡易名) としての意味が、 E type_name (名前空間と型名) としての意味と同じ型を持つ定数、フィールド、プロパティ、ローカル変数、またはパラメーターである場合、の両方の有効な意味 E が許可されます。In a member access of the form E.I, if E is a single identifier, and if the meaning of E as a simple_name (Simple names) is a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type_name (Namespace and type names), then both possible meanings of E are permitted. の2つの意味が E.I あいまいになることはありません。これは、必ず I しも両方の型のメンバーである必要があるため E です。The two possible meanings of E.I are never ambiguous, since I must necessarily be a member of the type E in both cases. つまり、この規則は、静的なメンバーおよび入れ子になった型にアクセスできるようにします。この場合、 E コンパイル時エラーが発生します。In other words, the rule simply permits access to the static members and nested types of E where a compile-time error would otherwise have occurred. 次に例を示します。For example:

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 、2つの引数 (と) を持つの呼び出しとして解釈される可能性があり G < A B > (7) ます。could be interpreted as a call to F with two arguments, G < A and B > (7). または、1つの引数を使用したの呼び出しとして解釈することもでき F ます。これは、  G 2 つの型引数と1つの標準引数を持つジェネリックメソッドの呼び出しです。Alternatively, it could be interpreted as a call to F with one argument, which is a call to a generic method G with two type arguments and one regular argument.

トークンのシーケンスを simple_name (簡易名)、 member_access (メンバーアクセス)、または pointer_member_access (ポインターメンバーアクセス) の最後に type_argument_list (型引数) として解析できる場合、終了トークンの直後にあるトークン > が検査されます。If a sequence of tokens can be parsed (in context) as a simple_name (Simple names), member_access (Member access), or pointer_member_access (Pointer member access) ending with a type_argument_list (Type arguments), the token immediately following the closing > token is examined. のいずれかである場合If it is one of

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

その後、 type_argument_listsimple_namemember_access または pointer_member_access の一部として保持され、その他のトークンシーケンスの解析はすべて破棄されます。then the type_argument_list is retained as part of the simple_name, member_access or pointer_member_access and any other possible parse of the sequence of tokens is discarded. それ以外の場合、トークンのシーケンスを解析できない場合でも、 type_argument_listsimple_namemember_access 、または pointer_member_access の一部とは見なされません。Otherwise, the type_argument_list is not considered to be part of the simple_name, member_access or pointer_member_access, even if there is no other possible parse of the sequence of tokens. これらの規則は、 namespace_or_type_name (名前空間と型名) の type_argument_list を解析するときには適用されないことに注意してください。Note that these rules are not applied when parsing a type_argument_list in a namespace_or_type_name (Namespace and type names). 次のステートメント、The statement

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

は、この規則に従って、1つの引数を使用したの呼び出しとして解釈されます。これは、2つの F G 型引数と1つの標準引数を持つジェネリックメソッドの呼び出しです。will, according to this rule, be interpreted as a call to F with one argument, which is a call to a generic method G with two type arguments and one regular argument. ステートメントThe statements

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

は、 F 2 つの引数を持つの呼び出しとして解釈されます。will each be interpreted as a call to F with two arguments. 次のステートメント、The statement

x = F < A > +y;

は、ステートメントが書き込まれたかのように、小なり演算子、大なり演算子、および単項プラス演算子として解釈されます。これは、 x = (F < A) > (+y) type_argument_list の後に二項プラス演算子が続く simple_name ではなくなります。will be interpreted as a less than operator, greater than operator, and unary plus operator, as if the statement had been written x = (F < A) > (+y), instead of as a simple_name with a type_argument_list followed by a binary plus operator. ステートメント内In the statement

x = y is C<T> + z;

トークン C<T> は、 type_argument_listnamespace_or_type_name として解釈されます。the tokens C<T> are interpreted as a namespace_or_type_name with a type_argument_list.

Invocation 式Invocation expressions

Invocation_expression は、メソッドを呼び出すために使用されます。An invocation_expression is used to invoke a method.

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

次のいずれかに当てはまる場合、 invocation_expression は動的にバインドされます (動的バインド)。An invocation_expression is dynamically bound (Dynamic binding) if at least one of the following holds:

  • Primary_expression にコンパイル時の型があり dynamic ます。The primary_expression has compile-time type dynamic.
  • オプションの argument_list の少なくとも1つの引数にコンパイル時の型があり、 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_expression を型の値として分類し dynamic ます。In this case the compiler classifies the invocation_expression as a value of type dynamic. 次の規則は、 invocation_expression の意味を判断するために、実行時に実行時に適用されます。これは、コンパイル時の型を持つ primary_expression および引数のコンパイル時の型ではなく、実行時の型を使用し dynamic ます。The rules below to determine the meaning of the invocation_expression are then applied at run-time, using the run-time type instead of the compile-time type of those of the primary_expression and arguments which have the compile-time type dynamic. Primary_expression にコンパイル時の型がない場合 dynamic 、メソッドの呼び出しでは、「動的なオーバーロードの解決のコンパイル時チェック」で説明されているように、コンパイル時間の制限があります。If the primary_expression does not have compile-time type dynamic, then the method invocation undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.

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.

省略可能な argument_list (引数リスト) は、メソッドのパラメーターの値または変数参照を提供します。The optional argument_list (Argument lists) provides values or variable references for the parameters of the method.

Invocation_expression を評価した結果は、次のように分類されます。The result of evaluating an invocation_expression is classified as follows:

  • Invocation_expression がを返すメソッドまたはデリゲートを呼び出すと、 void 結果は nothing になります。If the invocation_expression invokes a method or delegate that returns void, the result is nothing. Nothing として分類される式は、 statement_expression (式ステートメント) のコンテキスト、または lambda_expression (匿名関数式) の本体としてのみ許可されます。An expression that is classified as nothing is permitted only in the context of a statement_expression (Expression statements) or as the body of a lambda_expression (Anonymous function expressions). それ以外の場合、バインド時エラーが発生します。Otherwise a binding-time error occurs.
  • それ以外の場合、結果は、メソッドまたはデリゲートによって返される型の値になります。Otherwise, the result is a value of the type returned by the method or delegate.

メソッドの呼び出しMethod invocations

メソッド呼び出しの場合、 invocation_expressionprimary_expression はメソッドグループである必要があります。For a method invocation, the primary_expression of the invocation_expression must be a method group. メソッドグループは、呼び出す1つのメソッド、または特定のメソッドを呼び出すオーバーロードされたメソッドのセットを識別します。The method group identifies the one method to invoke or the set of overloaded methods from which to choose a specific method to invoke. 後者の場合、呼び出す特定のメソッドの決定は、 argument_list 内の引数の型によって提供されるコンテキストに基づいて行われます。In the latter case, determination of the specific method to invoke is based on the context provided by the types of the arguments in the argument_list.

フォームのメソッド呼び出しのバインド時の処理 M(A) 。ここで、 M はメソッドグループ ( type_argument_list など) であり、 A オプションの argument_list であり、次の手順で構成されています。The binding-time processing of a method invocation of the form M(A), where M is a method group (possibly including a type_argument_list), and A is an optional argument_list, consists of the following steps:

  • メソッド呼び出しの候補メソッドのセットが構築されます。The set of candidate methods for the method invocation is constructed. Fメソッドグループに関連付けられているメソッドごとに、次の手順を M 実行します。For each method F associated with the method group M:
    • Fが非ジェネリックの場合、 F は次の場合に候補になります。If F is non-generic, F is a candidate when:
    • 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).
  • 候補のメソッドのセットは、ほとんどの派生型からのメソッドのみを含むように縮小されます。 set 内のメソッドごとに、 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. さらに、 C が以外のクラス型である場合は、 object インターフェイス型で宣言されたすべてのメソッドがセットから削除されます。Furthermore, if C is a class type other than object, all methods declared in an interface type are removed from the set. (この後者の規則は、メソッドグループが、オブジェクト以外の有効な基本クラスと空でない有効なインターフェイスセットを持つ型パラメーターに対するメンバー参照の結果である場合にのみ影響を与えます)。(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. 1つの最適なメソッドを識別できない場合、メソッドの呼び出しがあいまいになり、バインディング時エラーが発生します。If a single best method cannot be identified, the method invocation is ambiguous, and a binding-time error occurs. オーバーロードの解決を実行する場合、ジェネリックメソッドのパラメーターは、対応するメソッドの型パラメーターに対して型引数 (指定または推論) を代入した後に考慮されます。When performing overload resolution, the parameters of a generic method are considered after substituting the type arguments (supplied or inferred) for the corresponding method type parameters.
  • 選択した最適な方法の最終的な検証が実行されます。Final validation of the chosen best method is performed:
    • メソッドは、メソッドグループのコンテキストで検証されます。最適なメソッドが静的メソッドの場合、メソッドグループは、型によって simple_name または member_access から生成されたものである必要があります。The method is validated in the context of the method group: If the best method is a static method, the method group must have resulted from a simple_name or a member_access through a type. 最適なメソッドがインスタンスメソッドの場合、メソッドグループの結果は、 simple_name、変数または値を使用した member_access 、または base_access である必要があります。If the best method is an instance method, the method group must have resulted from a simple_name, a member_access through a variable or value, or a base_access. これらの要件のいずれも当てはまらない場合は、バインド時エラーが発生します。If neither of these requirements is true, a binding-time error occurs.
    • 最適なメソッドがジェネリックメソッドの場合は、ジェネリックメソッドで宣言されている制約 (制約を満たす) に対して、型引数 (指定または推論) がチェックされます。If the best method is a generic method, the type arguments (supplied or inferred) are checked against the constraints (Satisfying constraints) declared on the generic method. 型引数が型パラメーターの対応する制約を満たしていない場合、バインド時エラーが発生します。If any type argument does not satisfy the corresponding constraint(s) on the type parameter, a binding-time error occurs.

前の手順でバインド時にメソッドを選択して検証すると、実際のランタイム呼び出しは、「 動的なオーバーロードの解決のコンパイル時チェック」で説明されている関数メンバー呼び出しの規則に従って処理されます。Once a method has been selected and validated at binding-time by the above steps, the actual run-time invocation is processed according to the rules of function member invocation described in Compile-time checking of dynamic overload resolution.

上記で説明した解決規則の直感的な効果は次のとおりです。メソッド呼び出しによって呼び出された特定のメソッドを検索するには、メソッドの呼び出しによって示された型から開始し、適用可能で、アクセス可能で、オーバーライド不可能なメソッド宣言が少なくとも1つ見つかるまで継承チェーンを進めます。The intuitive effect of the resolution rules described above is as follows: To locate the particular method invoked by a method invocation, start with the type indicated by the method invocation and proceed up the inheritance chain until at least one applicable, accessible, non-override method declaration is found. 次に、その型で宣言されている、アクセス可能で、オーバーライドできないメソッドのセットに対して、型の推定とオーバーロードの解決を実行し、選択したメソッドを呼び出します。Then perform type inference and overload resolution on the set of applicable, accessible, non-override methods declared in that type and invoke the method thus selected. メソッドが見つからなかった場合は、代わりに拡張メソッドの呼び出しとして呼び出しを処理するようにしてください。If no method was found, try instead to process the invocation as an extension method invocation.

拡張メソッドの呼び出しExtension method invocations

フォームのいずれかのメソッド呼び出し (ボックス化されたインスタンスでの呼び出し)In a method invocation (Invocations on boxed instances) of one of the forms

expr . identifier ( )

expr . identifier ( args )

expr . identifier < typeargs > ( )

expr . identifier < typeargs > ( args )

呼び出しの通常の処理で適用可能なメソッドが検出されなかった場合は、拡張メソッドの呼び出しとしてコンストラクトを処理しようとしました。if the normal processing of the invocation finds no applicable methods, an attempt is made to process the construct as an extension method invocation. Expr またはいずれかの 引数 にコンパイル時の型がある場合 dynamic 、拡張メソッドは適用されません。If expr or any of the args has compile-time type dynamic, extension methods will not apply.

目的は、最適な type_name を見つけて、 C 対応する静的メソッドの呼び出しを実行できるようにすることです。The objective is to find the best type_name C, so that the corresponding static method invocation can take place:

C . identifier ( expr )

C . identifier ( expr , args )

C . identifier < typeargs > ( expr )

C . identifier < typeargs > ( expr , args )

拡張メソッド Ci.Mj は、次の場合に 適し ています。An extension method Ci.Mj is eligible if:

  • Ci が非ジェネリックで、入れ子になっていないクラスです。Ci is a non-generic, non-nested class
  • の名前 Mjidentifier です。The name of Mj is identifier
  • Mj は、上記のように静的メソッドとして引数に適用した場合にアクセス可能であり、適用可能です。Mj is accessible and applicable when applied to the arguments as a static method as shown above
  • 暗黙的な id、参照、またはボックス化変換は、 expr からの最初のパラメーターの型への変換 Mj です。An implicit identity, reference or boxing conversion exists from expr to the type of the first parameter of Mj.

の検索は次のように行われ C ます。The search for C proceeds as follows:

  • 最も近い外側の名前空間宣言から開始し、外側の名前空間宣言のそれぞれを継続し、次に、一連の拡張メソッドを検索します。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.
    • Ci Using_static_declarations によってインポートされた型と、指定した名前空間またはコンパイル単位の using_namespace_directive s によってインポートされた名前空間で直接宣言された型が、対象となる拡張メソッドを直接含んでいる場合 Mj 、これらの拡張メソッドのセットは候補セットになります。If types Ci imported by using_static_declarations and directly declared in namespaces imported by using_namespace_directive s 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). 1つの最適なメソッドが見つからない場合は、コンパイル時エラーが発生します。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).

上記の規則は、インスタンスメソッドが拡張メソッドよりも優先されることを意味します。内部名前空間宣言で使用できる拡張メソッドは、外部名前空間宣言で使用できる拡張メソッドよりも優先されます。また、名前空間で直接宣言された拡張メソッドは、using namespace ディレクティブを使用して、同じ名前空間にインポートされた拡張メソッドThe preceding rules mean that instance methods take precedence over extension methods, that extension methods available in inner namespace declarations take precedence over extension methods available in outer namespace declarations, and that extension methods declared directly in a namespace take precedence over extension methods imported into that same namespace with a using namespace directive. 次に例を示します。For example:

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)
    }
}

この例では、 B のメソッドは最初の拡張メソッドよりも優先され、 C のメソッドは両方の拡張メソッドよりも優先されます。In the example, B's method takes precedence over the first extension method, and C's method takes precedence over both extension methods.

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();
        }
    }
}

この例の出力は次のようになります。The output of this example is:

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

D.G はより C.G も優先さ E.F れ、との両方に優先し D.F C.F ます。D.G takes precedence over C.G, and E.F takes precedence over both D.F and C.F.

デリゲートの呼び出しDelegate invocations

デリゲート呼び出しの場合、 invocation_expressionprimary_expressiondelegate_type の値である必要があります。For a delegate invocation, the primary_expression of the invocation_expression must be a value of a delegate_type. さらに、 delegate_typedelegate_type と同じパラメーターリストを持つ関数メンバーになることを考慮して、 delegate_typeinvocation_expressionargument_list に対して適用可能 (適用可能な関数メンバー) である必要があります。Furthermore, considering the delegate_type to be a function member with the same parameter list as the delegate_type, the delegate_type must be applicable (Applicable function member) with respect to the argument_list of the invocation_expression.

フォームのデリゲート呼び出しの実行時の処理 D(A) 。ここで、 Ddelegate_typeprimary_expression であり、 A オプションの argument_list であり、次の手順で構成されています。The run-time processing of a delegate invocation of the form D(A), where D is a primary_expression of a delegate_type and A is an optional argument_list, consists of the following steps:

  • D が評価されます。D is evaluated. この評価によって例外が発生した場合、それ以上の手順は実行されません。If this evaluation causes an exception, no further steps are executed.
  • の値 D が有効であるかどうかがチェックされます。The value of D is checked to be valid. の値がの場合は、が D null スローされ、 System.NullReferenceException それ以上の手順は実行されません。If the value of D is null, a System.NullReferenceException is thrown and no further steps are executed.
  • それ以外の場合、 D はデリゲートインスタンスへの参照です。Otherwise, D is a reference to a delegate instance. 関数メンバー呼び出し (動的なオーバーロード解決のコンパイル時チェック) は、デリゲートの呼び出しリスト内の呼び出し可能な各エンティティに対して実行されます。Function member invocations (Compile-time checking of dynamic overload resolution) are performed on each of the callable entities in the invocation list of the delegate. インスタンスメソッドとインスタンスメソッドで構成される呼び出し可能なエンティティの場合、呼び出しのインスタンスは、呼び出し可能なエンティティに含まれるインスタンスです。For callable entities consisting of an instance and instance method, the instance for the invocation is the instance contained in the callable entity.

要素アクセスElement access

Element_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 は、コンマで区切られた1つ以上の 引数 で構成されます。The argument_list consists of one or more argument s, separated by commas.

element_access
    : primary_no_array_creation_expression '[' expression_list ']'
    ;

Element_accessargument_list に、 ref または引数を含めることはできません outThe argument_list of an element_access is not allowed to contain ref or out arguments.

次のいずれかに当てはまる場合、 element_access は動的にバインドされます (動的バインド)。An element_access is dynamically bound (Dynamic binding) if at least one of the following holds:

  • Primary_no_array_creation_expression にコンパイル時の型があり dynamic ます。The primary_no_array_creation_expression has compile-time type dynamic.
  • Argument_list の少なくとも1つの式にコンパイル時の型があり、 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.

この場合、コンパイラは element_access を型の値として分類し dynamic ます。In this case the compiler classifies the element_access as a value of type dynamic. 次の規則は、 element_access の意味を判断するために、実行時に実行時に適用されます。これは、コンパイル時の型を持つ primary_no_array_creation_expression および argument_list 式のコンパイル時の型ではなく、実行時の型を使用し dynamic ます。The rules below to determine the meaning of the element_access are then applied at run-time, using the run-time type instead of the compile-time type of those of the primary_no_array_creation_expression and argument_list expressions which have the compile-time type dynamic. Primary_no_array_creation_expression にコンパイル時の型がない場合 dynamic 、「動的なオーバーロードの解決のコンパイル時のチェック」で説明されているように、要素へのアクセスにはコンパイル時間の制限があります。If the primary_no_array_creation_expression does not have compile-time type dynamic, then the element access undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.

Element_accessprimary_no_array_creation_expressionarray_type の値の場合、 element_access は配列アクセス (配列アクセス) です。If the primary_no_array_creation_expression of an element_access is a value of an array_type, the element_access is an array access (Array access). それ以外の場合、 primary_no_array_creation_expression は、1つ以上のインデクサーメンバーを持つクラス、構造体、またはインターフェイス型の変数または値である必要があります。この場合、 element_access はインデクサーアクセス (インデクサーアクセス) になります。Otherwise, the primary_no_array_creation_expression must be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the element_access is an indexer access (Indexer access).

配列へのアクセスArray access

配列アクセスの場合、 element_accessprimary_no_array_creation_expressionarray_type の値である必要があります。For an array access, the primary_no_array_creation_expression of the element_access must be a value of an array_type. さらに、配列アクセスの argument_list に名前付き引数を含めることはできません。 Argument_list 内の式の数は、 array_type のランクと同じである必要があります。また、各式は、、、、 int uint long ulong 、またはこれらの型の1つ以上に暗黙的に変換可能である必要があります。Furthermore, the argument_list of an array access is not allowed to contain named arguments.The number of expressions in the argument_list must be the same as the rank of the array_type, and each expression must be of type int, uint, long, ulong, or must be implicitly convertible to one or more of these types.

配列アクセスを評価した結果は、配列の要素型、つまり、 argument_list 内の式の値によって選択された配列要素の変数になります。The result of evaluating an array access is a variable of the element type of the array, namely the array element selected by the value(s) of the expression(s) in the argument_list.

フォームの配列アクセスの実行時処理 P[A] ( P は、 array_typeprimary_no_array_creation_expression であり、 A argument_list であり、次の手順で構成されています。The run-time processing of an array access of the form P[A], where P is a primary_no_array_creation_expression of an array_type and A is an argument_list, consists of the following steps:

  • P が評価されます。P 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. 次の各インデックス式の評価は、、、 int uint long 、のいずれかの型への暗黙的な変換 (暗黙の変換) によって行われ ulong ます。Following evaluation of each index expression, an implicit conversion (Implicit conversions) to one of the following types is performed: int, uint, long, ulong. 暗黙的な変換が存在する、この一覧の最初の型が選択されます。The first type in this list for which an implicit conversion exists is chosen. たとえば、インデックス式が型の場合は、 short からへの int 暗黙的 short な変換とからへの暗黙の変換が可能であるため、への暗黙的な変換が実行され int short long ます。For instance, if the index expression is of type short then an implicit conversion to int is performed, since implicit conversions from short to int and from short to long are possible. インデックス式またはそれ以降の暗黙的な変換の評価によって例外が発生した場合、それ以降のインデックス式は評価されず、それ以上の手順は実行されません。If evaluation of an index expression or the subsequent implicit conversion causes an exception, then no further index expressions are evaluated and no further steps are executed.
  • の値 P が有効であるかどうかがチェックされます。The value of P is checked to be valid. の値がの場合は、が P null スローされ、 System.NullReferenceException それ以上の手順は実行されません。If the value of P is null, a System.NullReferenceException is thrown and no further steps are executed.
  • Argument_list 内の各式の値は、によって参照される配列インスタンスの各次元の実際の境界に対してチェックされ P ます。The value of each expression in the argument_list is checked against the actual bounds of each dimension of the array instance referenced by P. 1つ以上の値が範囲外の場合は、 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

インデクサーアクセスの場合、 element_accessprimary_no_array_creation_expression はクラス、構造体、またはインターフェイス型の変数または値である必要があり、この型は element_accessargument_list に対して適用できる1つ以上のインデクサーを実装する必要があります。For an indexer access, the primary_no_array_creation_expression of the element_access must be a variable or value of a class, struct, or interface type, and this type must implement one or more indexers that are applicable with respect to the argument_list of the element_access.

フォームのインデクサーアクセスのバインド時の処理 P[A] 。ここで、 P はクラス、構造体、またはインターフェイス型の primary_no_array_creation_expressionT Aargument_list であり、次の手順で構成されています。The binding-time processing of an indexer access of the form P[A], where P is a primary_no_array_creation_expression of a class, struct, or interface type T, and A is an argument_list, consists of the following steps:

  • によって提供されるインデクサーのセット T が構築されます。The set of indexers provided by T is constructed. このセットは、で宣言されたすべてのインデクサー、 T または T 宣言ではなく、 override 現在のコンテキスト (メンバーアクセス) でアクセスできるの基本型で構成されます。The set consists of all indexers declared in T or a base type of T that are not override declarations and are accessible in the current context (Member access).
  • このセットは、他のインデクサーによって適用可能で非表示にされるインデクサーに限定されます。The set is reduced to those indexers that are applicable and not hidden by other indexers. 次の規則は、セット内の各インデクサーに適用され S.I S ます。ここで、は、インデクサー I が宣言されている型です。The following rules are applied to each indexer S.I in the set, where S is the type in which the indexer I is declared:
    • I A (適用可能な関数メンバー) に対してが適用されない場合は、 I セットからが削除されます。If I is not applicable with respect to A (Applicable function member), then I is removed from the set.
    • I(適用可能な関数メンバー) に対してを適用できる場合は、 A の基本型で宣言されたすべてのインデクサー S がセットから削除されます。If I is applicable with respect to A (Applicable function member), then all indexers declared in a base type of S are removed from the set.
    • IA (適用可能な関数メンバー) に対して適用可能で、 S 以外のクラス型である場合 object 、インターフェイスで宣言されたすべてのインデクサーがセットから削除されます。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. 1つの最適なインデクサーを識別できない場合、インデクサーアクセスはあいまいであり、バインド時エラーが発生します。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.

インデクサーアクセスは、使用されるコンテキストに応じて、インデクサーの get アクセサー または set アクセサー のいずれかを呼び出します。Depending on the context in which it is used, an indexer access causes invocation of either the get accessor or the set accessor of the indexer. インデクサーアクセスが割り当てのターゲットである場合は、 set アクセサー が呼び出され、新しい値 (単純な割り当て) が割り当てられます。If the indexer access is the target of an assignment, the set accessor is invoked to assign a new value (Simple assignment). それ以外の場合は、 get アクセサー を呼び出して現在の値 (式の値) を取得します。In all other cases, the get accessor is invoked to obtain the current value (Values of expressions).

このアクセス権This access

This_access は、予約語で構成さ this れます。A this_access consists of the reserved word this.

this_access
    : 'this'
    ;

This_access は、インスタンスコンストラクター、インスタンスメソッド、またはインスタンスアクセサーの ブロック 内でのみ許可されます。A this_access is permitted only in the block of an instance constructor, an instance method, or an instance accessor. 次のいずれかの意味があります。It has one of the following meanings:

  • this クラスのインスタンスコンストラクター内の primary_expression で使用すると、値として分類されます。When this is used in a primary_expression within an instance constructor of a class, it is classified as a value. 値の型は、使用が発生するクラスのインスタンス型 (インスタンス型) であり、値は構築されているオブジェクトへの参照です。The type of the value is the instance type (The instance type) of the class within which the usage occurs, and the value is a reference to the object being constructed.
  • thisクラスのインスタンスメソッドまたはインスタンスアクセサー内の primary_expression でを使用すると、値として分類されます。When this is used in a primary_expression within an instance method or instance accessor of a class, it is classified as a value. 値の型は、使用が発生するクラスのインスタンスの型 (インスタンス型) です。この値は、メソッドまたはアクセサーが呼び出されたオブジェクトへの参照です。The type of the value is the instance type (The instance type) of the class within which the usage occurs, and the value is a reference to the object for which the method or accessor was invoked.
  • thisが構造体のインスタンスコンストラクター内の primary_expression で使用されている場合は、変数として分類されます。When this is used in a primary_expression within an instance constructor of a struct, it is classified as a variable. 変数の型は、使用が発生する構造体のインスタンス型 (インスタンス型) であり、変数は構築されている構造体を表します。The type of the variable is the instance type (The instance type) of the struct within which the usage occurs, and the variable represents the struct being constructed. this構造体のインスタンスコンストラクターの変数は、構造体型のパラメーターとまったく同じように動作し out ます。具体的には、インスタンスコンストラクターのすべての実行パスで変数を確実に代入する必要があります。The this variable of an instance constructor of a struct behaves exactly the same as an out parameter of the struct type—in particular, this means that the variable must be definitely assigned in every execution path of the instance constructor.
  • thisが、構造体のインスタンスメソッドまたはインスタンスアクセサー内の primary_expression で使用されている場合は、変数として分類されます。When this is used in a primary_expression within an instance method or instance accessor of a struct, it is classified as a variable. 変数の型は、使用状況が発生する構造体のインスタンスの型 (インスタンス型) です。The type of the variable is the instance type (The instance type) of the struct within which the usage occurs.
    • メソッドまたはアクセサーが反復子 (反復子) でない場合、変数は、 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.

上に this 示したものとは別のコンテキストの primary_expression でを使用すると、コンパイル時エラーになります。Use of this in a primary_expression in a context other than the ones listed above is a compile-time error. 特に、 this 静的メソッド、静的プロパティアクセサー、またはフィールド宣言の variable_initializer でを参照することはできません。In particular, it is not possible to refer to this in a static method, a static property accessor, or in a variable_initializer of a field declaration.

基本アクセスBase access

Base_access は、予約語の base 後に " . " トークンと識別子、または角かっこで囲まれた argument_list で構成されます。A 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_access は、インスタンスコンストラクター、インスタンスメソッド、またはインスタンスアクセサーの ブロック 内でのみ許可されます。A 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_accessbase.I base[E] は、記述されたものとまったく同じように評価され ((B)this).I ((B)this)[E] B ます。ここで、は、コンストラクトが発生するクラスまたは構造体の基本クラスです。At binding-time, base_access expressions of the form base.I and base[E] are evaluated exactly as if they were written ((B)this).I and ((B)this)[E], where B is the base class of the class or struct in which the construct occurs. したがって、とは、 base.I base[E] とに対応し this.I this[E] this ます。ただし、は基底クラスのインスタンスとして表示されます。Thus, base.I and base[E] correspond to this.I and this[E], except this is viewed as an instance of 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). したがって、関数メンバーの内では、 override virtual 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 によって参照される関数メンバーが abstract の場合、バインド時エラーが発生します。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 '--'
    ;

後置インクリメントまたはデクリメント演算のオペランドには、変数、プロパティアクセス、またはインデクサーアクセスとして分類される式を指定する必要があります。The operand of a postfix increment or decrement operation must be an expression classified as a variable, a property access, or an indexer access. 演算の結果は、オペランドと同じ型の値になります。The result of the operation is a value of the same type as the operand.

Primary_expression にコンパイル時の型がある場合、 dynamic 演算子は動的バインド (動的バインド)、 post_increment_expression または post_decrement_expression にはコンパイル時の型があり、実行時 dynamic には primary_expression の実行時の型を使用して次の規則が適用されます。If the primary_expression has the compile-time type dynamic then the operator is dynamically bound (Dynamic binding), the post_increment_expression or post_decrement_expression has the compile-time type dynamic and the following rules are applied at run-time using the run-time type of the primary_expression.

後置インクリメントまたはデクリメント演算のオペランドがプロパティまたはインデクサーアクセスの場合は、プロパティまたはインデクサーにとアクセサーの両方が必要 get set です。If the operand of a postfix increment or decrement operation is a property or indexer access, the property or indexer must have both a get and a set accessor. そうでない場合は、バインド時エラーが発生します。If this is not the case, a binding-time error occurs.

単項演算子のオーバーロードの解決 (単項演算子のオーバーロードの解決) は、特定の演算子の実装を選択するために適用されます。Unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. 、、、、、、、、、、、、およびの各 ++ -- sbyte byte short ushort int uint long ulong char float double decimal 列挙型には、定義済みの演算子と演算子が存在します。Predefined ++ and -- operators exist for the following types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, and any enum type. 定義済みの演算子は、 ++ オペランドに1を加算して生成された値を返します。定義済みの演算子は、 -- オペランドから1を減算して生成された値を返します。The predefined ++ operators return the value produced by adding 1 to the operand, and the predefined -- operators return the value produced by subtracting 1 from the operand. コンテキストで checked 、この加算または減算の結果が結果型の範囲外で、結果型が整数型または列挙型である場合、 System.OverflowException がスローされます。In a checked context, if the result of this addition or subtraction is outside the range of the result type and the result type is an integral type or enum type, a System.OverflowException is thrown.

フォームまたはの後置インクリメントまたはデクリメント操作の実行時の処理は、次の手順で構成されてい x++ x-- ます。The run-time processing of a postfix increment or decrement operation of the form x++ or x-- consists of the following steps:

  • xが変数として分類される場合は、次のようになります。If x is classified as a variable:
    • x は、変数を生成するために評価されます。x is evaluated to produce the variable.
    • の値 x が保存されます。The value of x is saved.
    • 選択された演算子は、の引数として、保存された値を使用して呼び出され x ます。The selected operator is invoked with the saved value of x as its argument.
    • 演算子によって返される値は、の評価によって指定された場所に格納され x ます。The value returned by the operator is stored in the location given by the evaluation of x.
    • の保存された値は、 x 操作の結果になります。The saved value of x becomes the result of the operation.
  • xがプロパティまたはインデクサーアクセスとして分類される場合は、次のようになります。If x is classified as a property or indexer access:
    • インスタンス式 (がで x はない場合) static およびに関連付けられた引数リスト ( x がインデクサーアクセスの場合) x が評価され、その結果が後続のおよびアクセサー呼び出しで使用され get 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 get and set accessor invocations.
    • getのアクセサー x が呼び出され、戻り値が保存されます。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.
    • setのアクセサー x は、演算子によって返された値を引数として使用して呼び出され value ます。The set accessor of x is invoked with the value returned by the operator as its value argument.
    • の保存された値は、 x 操作の結果になります。The saved value of x becomes the result of the operation.

++And 演算子は、 -- 前置表記 (前置インクリメントおよびデクリメント演算子) もサポートしています。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.

operator ++またはの実装は、 operator -- 後置表記またはプレフィックス表記のいずれかを使用して呼び出すことができます。An operator ++ or operator -- implementation can be invoked using either postfix or prefix notation. 2つの表記に対して個別の演算子を実装することはできません。It is not possible to have separate operator implementations for the two notations.

新しい演算子The new operator

new演算子は、型の新しいインスタンスを作成するために使用されます。The new operator is used to create new instances of types.

式には、次の3つの形式があり new ます。There are three forms of new expressions:

  • オブジェクト作成式は、クラス型と値型の新しいインスタンスを作成するために使用されます。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_type または value_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_type 、または type_parameter である必要があります。The type of an object_creation_expression must be a class_type, a value_type or a type_parameter. を class_type にすることはできません abstractThe type cannot be an abstract class_type.

省略可能な argument_list (引数リスト) は、 class_type または struct_type の場合にのみ許可されます。The optional argument_list (Argument lists) is permitted only if the type is a class_type or a struct_type.

オブジェクトの作成式では、コンストラクターの引数リストと、オブジェクト初期化子またはコレクション初期化子が含まれている場合に囲むかっこを省略できます。An object creation expression can omit the constructor argument list and enclosing parentheses provided it includes an object initializer or collection initializer. コンストラクターの引数リストと囲んでいるかっこを省略することは、空の引数リストを指定することと同じです。Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.

オブジェクト初期化子またはコレクション初期化子を含むオブジェクト作成式の処理では、最初にインスタンスコンストラクターを処理した後、オブジェクト初期化子 (オブジェクト初期化子) またはコレクション初期化子 (コレクション初期化子) によって指定されたメンバーまたは要素の初期化を処理します。Processing of an object creation expression that includes an object initializer or collection initializer consists of first processing the instance constructor and then processing the member or element initializations specified by the object initializer (Object initializers) or collection initializer (Collection initializers).

省略可能な argument_list 内のいずれかの引数にコンパイル時の型がある場合 dynamicobject_creation_expression は動的にバインドされ (動的バインディング)、次の規則は、コンパイル時の型を持つ argument_list の引数の実行時の型を使用して実行時に適用され dynamic ます。If any of the arguments in the optional argument_list has the compile-time type dynamic then the object_creation_expression is dynamically bound (Dynamic binding) and the following rules are applied at run-time using the run-time type of those arguments of the argument_list that have the compile time type dynamic. ただし、オブジェクトの作成では、「 動的なオーバーロードの解決のコンパイル時チェック」で説明されているように、コンパイル時間の制限があります。However, the object creation undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.

フォームの object_creation_expression のバインド時の処理 new T(A) 。ここで、 Tclass_type または value_type であり、 A 省略可能な argument_list で、次の手順で構成されています。The binding-time processing of an object_creation_expression of the form new T(A), where T is a class_type or a value_type and A is an optional argument_list, consists of the following steps:

  • 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 つまり、の既定値は、 T ValueType 型で定義されています。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_type または struct_type の場合は、次のようになります。Otherwise, 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). 候補インスタンスコンストラクターのセットが空である場合、または1つの最適なインスタンスコンストラクターを識別できない場合は、バインディング時エラーが発生します。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.

Object_creation_expression が動的にバインドされている場合でも、コンパイル時の型はそのままです TEven if the object_creation_expression is dynamically bound, the compile-time type is still T.

フォームの object_creation_expression の実行時処理 new T(A) ( Tclass_type または struct_type であり、オプションの argument_list である場合、 A 次の手順で構成されます。 The run-time processing of an object_creation_expression of the form new T(A), where T is class_type or a struct_type and A is an optional argument_list, consists of the following steps:

  • Tclass_type の場合:If 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_type の場合:If 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

オブジェクト 初期化子 は、オブジェクトの0個以上のフィールド、プロパティ、またはインデックス付き要素の値を指定します。An object initializer specifies values for zero or more fields, properties or indexed elements of an object.

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
    ;

オブジェクト初期化子は、 { およびトークンで囲まれ、コンマで区切られた一連のメンバー初期化子で構成さ } れます。An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas. member_initializer は、初期化のターゲットを指定します。Each member_initializer designates a target for the initialization. 識別子 は、初期化されるオブジェクトのアクセス可能なフィールドまたはプロパティに名前を付ける必要があります。一方、角かっこで囲まれた argument_list は、初期化されるオブジェクトのアクセス可能なインデクサーの引数を指定する必要があります。An identifier must name an accessible field or property of the object being initialized, whereas an argument_list enclosed in square brackets must specify arguments for an accessible indexer on the object being initialized. オブジェクト初期化子に、同じフィールドまたはプロパティに対して複数のメンバー初期化子が含まれていると、エラーになります。It is an error for an object initializer to include more than one member initializer for the same field or property.

initializer_target には、等号と、式、オブジェクト初期化子、またはコレクション初期化子のいずれかが続きます。Each initializer_target is followed by an equals sign and either an expression, an object initializer or a collection initializer. オブジェクト初期化子内の式は、初期化中の新しく作成されたオブジェクトを参照することはできません。It is not possible for expressions within the object initializer to refer to the newly created object it is initializing.

等号の後にある式を指定するメンバー初期化子は、ターゲットへの代入 (単純な代入) と同じ方法で処理されます。A member initializer that specifies an expression after the equals sign is processed in the same way as an assignment (Simple assignment) to the target.

等号の後にオブジェクト初期化子を指定するメンバー初期化子は、入れ子になったオブジェクト 初期化子、つまり埋め込みオブジェクトの初期化です。A member initializer that specifies an object initializer after the equals sign is a nested object initializer, i.e. an initialization of an embedded object. フィールドまたはプロパティに新しい値を割り当てる代わりに、入れ子になったオブジェクト初期化子の割り当ては、フィールドまたはプロパティのメンバーへの割り当てとして扱われます。Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property. 入れ子になったオブジェクト初期化子は、値型のプロパティ、または値の型を持つ読み取り専用フィールドには適用できません。Nested object initializers cannot be applied to properties with a value type, or to read-only fields with a value type.

等号の後にコレクション初期化子を指定するメンバー初期化子は、埋め込みコレクションを初期化します。A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. ターゲットフィールド、プロパティ、またはインデクサーに新しいコレクションを割り当てる代わりに、初期化子に指定された要素が、ターゲットによって参照されるコレクションに追加されます。Instead of assigning a new collection to the target field, property or indexer, the elements given in the initializer are added to the collection referenced by the target. ターゲットは、 コレクション初期化子に指定された要件を満たすコレクション型である必要があります。The target must be of a collection type that satisfies the requirements specified in Collection initializers.

インデックス初期化子への引数は、常に1回だけ評価されます。The arguments to an index initializer will always be evaluated exactly once. したがって、引数が最終的に使用されない場合 (たとえば、入れ子になった空の初期化子があるため)、副作用について評価されます。Thus, even if the arguments end up never getting used (e.g. because of an empty nested initializer), they will be evaluated for their side effects.

次のクラスは、2つの座標を持つ点を表します。The following class represents a point with two coordinates:

public class Point
{
    int x, y;

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

のインスタンスは、次のようにし Point て作成および初期化できます。An instance of Point can be created and initialized as follows:

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

これは、which has the same effect as

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

ここで __a 、は非表示であり、アクセスできない一時的な変数です。where __a is an otherwise invisible and inaccessible temporary variable. 次のクラスは、2つの点から作成された四角形を表します。The following class represents a rectangle created from two points:

public class Rectangle
{
    Point p1, p2;

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

のインスタンスは、次のようにし Rectangle て作成および初期化できます。An instance of Rectangle can be created and initialized as follows:

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

これは、which has the same effect as

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;

ここ __r で、 __p1__p2 は、非表示でアクセスできない一時的な変数です。where __r, __p1 and __p2 are temporary variables that are otherwise invisible and inaccessible.

Rectangleのコンストラクターが2つの埋め込みインスタンスを割り当てる場合 PointIf Rectangle's constructor allocates the two embedded Point instances

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

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

次のコンストラクトは、新しいインスタンスを割り当てる代わりに、埋め込みインスタンスを初期化するために使用でき Point ます。the following construct can be used to initialize the embedded Point instances instead of assigning new instances:

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

これは、which has the same effect as

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

次の例では、C の適切な定義が指定されています。Given an appropriate definition of C, the following example:

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

は、次の一連の代入と同じです。is equivalent to this series of assignments:

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

ここ __c で、は、ソースコードからは見えず、アクセスできない、生成された変数です。where __c, etc., are generated variables that are invisible and inaccessible to the source code. の引数は [0,0] 1 回だけ評価され、の引数は、 [1,2] 使用されていない場合でも1回評価されることに注意してください。Note that the arguments for [0,0] are evaluated only once, and the arguments for [1,2] are evaluated once even though they are never used.

コレクション初期化子Collection initializers

コレクション初期化子は、コレクションの要素を指定します。A collection initializer specifies the elements of a collection.

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)*
    ;

コレクション初期化子は、要素初期化子のシーケンスで構成さ { れ、トークンとトークンで囲ま } れ、コンマで区切られます。A collection initializer consists of a sequence of element initializers, enclosed by { and } tokens and separated by commas. 各要素初期化子は、初期化されるコレクションオブジェクトに追加する要素を指定します。また、との各 { トークンで囲まれ、コンマで区切られた式のリストで構成され } ます。Each element initializer specifies an element to be added to the collection object being initialized, and consists of a list of expressions enclosed by { and } tokens and separated by commas. 単一式の要素初期化子は、かっこを使用せずに記述できますが、メンバー初期化子とのあいまいさを避けるために代入式にすることはできません。A single-expression element initializer can be written without braces, but cannot then be an assignment expression, to avoid ambiguity with member initializers. Non_assignment_expression の運用環境は、で定義されます。The non_assignment_expression production is defined in Expression.

次に、コレクション初期化子を含むオブジェクト作成式の例を示します。The following is an example of an object creation expression that includes a collection initializer:

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

コレクション初期化子が適用されるコレクションオブジェクトは、を実装する型である System.Collections.IEnumerable か、またはコンパイル時のエラーが発生します。The collection object to which a collection initializer is applied must be of a type that implements System.Collections.IEnumerable or a compile-time error occurs. コレクション初期化子は、指定された要素ごとに、 Add 引数リストとして要素初期化子の式リストを使用してターゲットオブジェクトに対してメソッドを呼び出し、各呼び出しに対して通常のメンバー参照とオーバーロードの解決を適用します。For each specified element in order, the collection initializer invokes an Add method on the target object with the expression list of the element initializer as argument list, applying normal member lookup and overload resolution for each invocation. したがって、コレクションオブジェクトには、 Add 各要素初期化子の名前を持つ適切なインスタンスまたは拡張メソッドが必要です。Thus, the collection object must have an applicable instance or extension method with the name Add for each element initializer.

次のクラスは、名前と電話番号のリストを持つ連絡先を表します。The following class represents a contact with a name and a list of phone numbers:

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

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

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

は、次のようにし List<Contact> て作成および初期化できます。A List<Contact> can be created and initialized as follows:

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

これは、which has the same effect as

var __clist = new List<Contact>();
Contact __c1 = new Contact();
__c1.Name = "Chris Smith";
__c1.PhoneNumbers.Add("206-555-0101");
__c1.PhoneNumbers.Add("425-882-8080");
__clist.Add(__c1);
Contact __c2 = new Contact();
__c2.Name = "Bob Harris";
__c2.PhoneNumbers.Add("650-555-0199");
__clist.Add(__c2);
var contacts = __clist;

ここ __clist で、 __c1__c2 は、非表示でアクセスできない一時的な変数です。where __clist, __c1 and __c2 are temporary variables that are otherwise invisible and inaccessible.

配列作成式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
    ;

最初の形式の配列作成式は、式リストから各式を削除した結果として得られる型の配列インスタンスを割り当てます。An array creation expression of the first form allocates an array instance of the type that results from deleting each of the individual expressions from the expression list. たとえば、配列作成式は new int[10,20] 型の配列インスタンスを生成 int[,] し、配列作成式は new int[10][,] 型の配列を生成し int[][,] ます。For example, the array creation expression new int[10,20] produces an array instance of type int[,], and the array creation expression new int[10][,] produces an array of type int[][,]. 式リストの各式は、、、、または型であるか、または int uint これらの long ulong 型の1つ以上に暗黙的に変換できなければなりません。Each expression in the expression list must be of type int, uint, long, or ulong, or implicitly convertible to one or more of these types. 各式の値によって、新しく割り当てられた配列インスタンス内の対応する次元の長さが決まります。The value of each expression determines the length of the corresponding dimension in the newly allocated array instance. 配列の次元の長さは負ではない必要があるため、式の一覧に負の値を持つ constant_expression を持つコンパイル時エラーが発生します。Since the length of an array dimension must be nonnegative, it is a compile-time error to have a constant_expression with a negative value in the expression list.

Unsafe コンテキスト (unsafeコンテキスト) の場合を除き、配列のレイアウトは指定されません。Except in an unsafe context (Unsafe contexts), the layout of arrays is unspecified.

最初の形式の配列作成式に配列初期化子が含まれている場合、式リスト内の各式は定数である必要があり、式リストで指定されたランクと次元の長さは配列初期化子の式と一致する必要があります。If an array creation expression of the first form includes an array initializer, each expression in the expression list must be a constant and the rank and dimension lengths specified by the expression list must match those of the array initializer.

2番目または3番目の形式の配列作成式では、指定された配列型またはランク指定子のランクが配列初期化子のランクと一致している必要があります。In an array creation expression of the second or third form, the rank of the specified array type or rank specifier must match that of the array initializer. 個々の次元の長さは、配列初期化子の対応する入れ子のレベルそれぞれに含まれる要素の数から推論されます。The individual dimension lengths are inferred from the number of elements in each of the corresponding nesting levels of the array initializer. したがって、式Thus, the expression

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

完全に対応exactly corresponds to

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

3番目の形式の配列作成式は、* 暗黙的に 型指定された配列作成式 _ と呼ばれます。An array creation expression of the third form is referred to as an *implicitly typed array creation expression _. 2番目の形式に似ていますが、配列の要素の型は明示的に指定されていませんが、配列初期化子内の式のセットの最適な共通型 (式セットの最適な共通型) として決定される点が異なります。It is similar to the second form, except that the element type of the array is not explicitly given, but determined as the best common type (Finding the best common type of a set of expressions) of the set of expressions in the array initializer. 多次元配列の場合、つまり、_rank_specifier * に少なくとも1つのコンマが含まれている場合、このセットは入れ子になった array_initializer s で見つかったすべての で構成されます。For a multidimensional array, i.e., one where the _rank_specifier* contains at least one comma, this set comprises all expression s found in nested array_initializer s.

配列初期化子の詳細については、「 配列初期化子」を参照してください。Array initializers are described further in Array initializers.

配列作成式を評価した結果は、新たに割り当てられた配列インスタンスへの参照として、値として分類されます。The result of evaluating an array creation expression is classified as a value, namely a reference to the newly allocated array instance. 配列作成式の実行時の処理は、次の手順で構成されます。The run-time processing of an array creation expression consists of the following steps:

  • Expression_list のディメンション長式は、左から右の順に評価されます。The dimension length expressions of the expression_list are evaluated in order, from left to right. 各式を評価すると、、、 int uint longulong のいずれかの型への暗黙的な変換 (暗黙の変換) が実行されます。Following 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. 1つ以上の値が0未満の場合は、 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).

配列作成式では、配列型の要素を含む配列のインスタンス化が許可されますが、このような配列の要素は手動で初期化する必要があります。An array creation expression permits instantiation of an array with elements of an array type, but the elements of such an array must be manually initialized. ステートメントの例を次に示します。For example, the statement

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

型の100要素を持つ1次元配列を作成し int[] ます。creates a single-dimensional array with 100 elements of type int[]. 各要素の初期値は null です。The initial value of each element is null. 同じ配列作成式で、サブ配列とステートメントをインスタンス化することはできません。It is not possible for the same array creation expression to also instantiate the sub-arrays, and the statement

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

コンパイル時エラーが発生します。results in a compile-time error. 代わりに、サブ配列のインスタンス化を手動で実行する必要があります。Instantiation of the sub-arrays must instead be performed manually, as in

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

配列の配列に "四角形" の形状がある場合、つまり、サブ配列の長さがすべて同じである場合は、多次元配列を使用する方が効率的です。When an array of arrays has a "rectangular" shape, that is when the sub-arrays are all of the same length, it is more efficient to use a multi-dimensional array. 上の例では、配列の配列のインスタンス化によって101オブジェクト (1 つの外部配列と100サブ配列) が作成されます。In the example above, instantiation of the array of arrays creates 101 objects—one outer array and 100 sub-arrays. それに対してIn contrast,

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

1つのオブジェクトと2次元配列だけを作成し、1つのステートメントで割り当てを行います。creates only a single object, a two-dimensional array, and accomplishes the allocation in a single statement.

暗黙的に型指定された配列作成式の例を次に示します。The following are examples of implicitly typed array creation expressions:

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

とが暗黙的に他方に変換できないため、最後の式によってコンパイル時エラーが発生 int string します。したがって、最適な共通型がありません。The last expression causes a compile-time error because neither int nor string is implicitly convertible to the other, and so there is no best common type. この場合は、型を指定するなど、明示的に型指定された配列作成式を使用する必要があり object[] ます。An explicitly typed array creation expression must be used in this case, for example specifying the type to be object[]. または、要素の1つを共通の基本型にキャストして、その要素の型が推論されるようにすることもできます。Alternatively, one of the elements can be cast to a common base type, which would then become the inferred element type.

暗黙的に型指定された配列作成式を匿名オブジェクト初期化子 (匿名オブジェクト作成式) と組み合わせて、匿名型のデータ構造を作成することができます。Implicitly typed array creation expressions can be combined with anonymous object initializers (Anonymous object creation expressions) to create anonymously typed data structures. 次に例を示します。For example:

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 ')'
    ;

デリゲート作成式の引数は、メソッドグループ、匿名関数、またはコンパイル時の型または delegate_type のいずれかの値である必要があり dynamic ます。 The argument of a delegate creation expression must be a method group, an anonymous function or a value of either the compile time type dynamic or a delegate_type. 引数がメソッドグループの場合、メソッドと、インスタンスメソッドの場合は、デリゲートを作成する対象のオブジェクトを識別します。If the argument is a method group, it identifies the method and, for an instance method, the object for which to create a delegate. 引数が匿名関数の場合、デリゲートターゲットのパラメーターとメソッドの本体が直接定義されます。If the argument is an anonymous function it directly defines the parameters and method body of the delegate target. 引数が値の場合は、コピーを作成する対象のデリゲートインスタンスを識別します。If the argument is a value it identifies a delegate instance of which to create a copy.

にコンパイル時の型がある場合 dynamicdelegate_creation_expression は動的にバインドされ (動的バインディング)、次の規則は実行時に の実行時の型を使用して適用されます。If the expression has the compile-time type dynamic, the delegate_creation_expression is dynamically bound (Dynamic binding), and the rules below are applied at run-time using the run-time type of the expression. それ以外の場合は、コンパイル時に規則が適用されます。Otherwise the rules are applied at compile-time.

フォームの delegate_creation_expression のバインド時の処理 new D(E) 。は delegate_type であり、 D E です。は、次の手順で構成されています。The binding-time processing of a delegate_creation_expression of the form new D(E), where D is a delegate_type and E is an expression, consists of the following steps:

  • Eがメソッドグループの場合、デリゲート作成式は、メソッドグループの変換 (メソッドグループの変換) と同じ方法でからに処理され E D ます。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が匿名関数の場合、デリゲート作成式は、からへの匿名関数変換 (匿名関数変換) と同じ方法で処理され E D ます。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. Eがと互換性がない場合 D 、コンパイル時エラーが発生します。If E is not compatible with D, a compile-time error occurs.

フォームの delegate_creation_expression の実行時処理。ここで、 new D(E) は delegate_type であり、 D E です。は、次の手順で構成されています。The run-time processing of a delegate_creation_expression of the form new D(E), where D is a delegate_type and E is an expression, consists of the following steps:

  • 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が匿名関数の場合、デリゲートの作成は、から E D (匿名関数の変換) への匿名関数の変換として評価されます。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:
    • E が評価されます。E is evaluated. この評価によって例外が発生した場合、それ以上の手順は実行されません。If this evaluation causes an exception, no further steps are executed.
    • の値がの場合は、が E null スローされ、 System.NullReferenceException それ以上の手順は実行されません。If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.
    • デリゲート型の新しいインスタンス D が割り当てられます。A new instance of the delegate type D is allocated. 新しいインスタンスを割り当てるのに十分なメモリがない場合は、 System.OutOfMemoryException がスローされ、それ以上の手順は実行されません。If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
    • 新しいデリゲートインスタンスは、によって指定されたデリゲートインスタンスと同じ呼び出しリストを使用して初期化され E ます。The new delegate instance is initialized with the same invocation list as the delegate instance given by E.

デリゲートの呼び出しリストは、デリゲートがインスタンス化されるときに決定され、その後、デリゲートの有効期間全体にわたって定数のままになります。The invocation list of a delegate is determined when the delegate is instantiated and then remains constant for the entire lifetime of the delegate. つまり、作成されたデリゲートのターゲット呼び出し可能エンティティを変更することはできません。In other words, it is not possible to change the target callable entities of a delegate once it has been created. 2つのデリゲートを結合する場合、または一方を別のデリゲート宣言 (デリゲート宣言) から削除する場合は、新しいデリゲートの結果はです。既存のデリゲートの内容が変更されていません。When two delegates are combined or one is removed from another (Delegate declarations), a new delegate results; no existing delegate has its contents changed.

プロパティ、インデクサー、ユーザー定義の演算子、インスタンスコンストラクター、デストラクター、または静的コンストラクターを参照するデリゲートを作成することはできません。It is not possible to create a delegate that refers to a property, indexer, user-defined operator, instance constructor, destructor, or static constructor.

前述のように、メソッドグループからデリゲートを作成すると、デリゲートの仮パラメーターリストと戻り値の型によって、どのオーバーロードされたメソッドを選択するかが決まります。As described above, when a delegate is created from a method group, the formal parameter list and return type of the delegate determine which of the overloaded methods to select. この例では、In the example

delegate double DoubleFunc(double x);

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

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

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

フィールドは、 A.f 2 番目のメソッドを参照するデリゲートで初期化されます。このメソッドは、 Square の仮パラメーターリストおよび戻り値の型と完全に一致し DoubleFunc ます。the A.f field is initialized with a delegate that refers to the second Square method because that method exactly matches the formal parameter list and return type of DoubleFunc. 2番目の Square メソッドが存在しない場合、コンパイル時エラーが発生しました。Had the second Square method not been present, a compile-time error would have occurred.

匿名オブジェクト作成式Anonymous object creation expressions

Anonymous_object_creation_expression は、匿名型のオブジェクトを作成するために使用されます。An anonymous_object_creation_expression is used to create an object of an anonymous type.

anonymous_object_creation_expression
    : 'new' anonymous_object_initializer
    ;

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

member_declarator_list
    : member_declarator (',' member_declarator)*
    ;

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

匿名オブジェクト初期化子は、匿名型を宣言し、その型のインスタンスを返します。An anonymous object initializer declares an anonymous type and returns an instance of that type. 匿名型は、から直接継承する無名のクラス型です objectAn anonymous type is a nameless class type that inherits directly from object. 匿名型のメンバーは、型のインスタンスを作成するために使用される匿名オブジェクト初期化子から推論される読み取り専用プロパティのシーケンスです。The members of an anonymous type are a sequence of read-only properties inferred from the anonymous object initializer used to create an instance of the type. 具体的には、フォームの匿名オブジェクト初期化子Specifically, an anonymous object initializer of the form

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

フォームの匿名型を宣言します。declares an anonymous type of the form

class __Anonymous1
{
    private readonly T1 f1;
    private readonly T2 f2;
    ...
    private readonly Tn fn;

    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() { ... }
}

ここで、各 Tx は対応する式の型です exwhere each Tx is the type of the corresponding expression ex. Member_declarator で使用する式には型が必要です。The expression used in a member_declarator must have a type. したがって、 member_declarator 内の式が null または匿名関数である場合、コンパイル時エラーになります。Thus, it is a compile-time error for an expression in a member_declarator to be null or an anonymous function. また、式に安全でない型がある場合のコンパイル時エラーでもあります。It is also a compile-time error for the expression to have an unsafe type.

匿名型の名前とそのメソッドへのパラメーターの名前 Equals は、コンパイラによって自動的に生成され、プログラムテキストで参照することはできません。The names of an anonymous type and of the parameter to its Equals method are automatically generated by the compiler and cannot be referenced in program text.

同じプログラム内で、同じ名前の一連のプロパティとコンパイル時の型を同じ順序で指定する2つの匿名オブジェクト初期化子は、同じ匿名型のインスタンスを生成します。Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and compile-time types in the same order will produce instances of the same anonymous type.

この例では、In the example

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

p1とが同じ匿名型であるため、最後の行の代入が許可され p2 ます。the assignment on the last line is permitted because p1 and p2 are of the same anonymous type.

Equals GetHashcode 匿名型のメソッドとメソッドは、から継承されたメソッドをオーバーライド object し、プロパティのとの観点で定義され Equals GetHashcode ます。これにより、同じ匿名型の2つのインスタンスが等しい場合に限り、同じ匿名型の2つのインスタンスが等しいようになります。The Equals and GetHashcode methods on anonymous types override the methods inherited from object, and are defined in terms of the Equals and GetHashcode of the properties, so that two instances of the same anonymous type are equal if and only if all their properties are equal.

メンバー宣言子は、単純な名前 (型の推定)、メンバーアクセス (動的なオーバーロードの解決のコンパイル時のチェック)、基本アクセス (基本アクセス)、または null 条件付きのメンバーアクセス (プロジェクション初期化子としての null 条件式) に省略できます。A member declarator can be abbreviated to a simple name (Type inference), a member access (Compile-time checking of dynamic overload resolution), a base access (Base access) or a null-conditional member access (Null-conditional expressions as projection initializers). これは、 射影初期化子 と呼ばれ、同じ名前を持つプロパティの宣言と代入のための短縮形です。This is called a projection initializer and is shorthand for a declaration of and assignment to a property with the same name. 具体的には、フォームのメンバー宣言子Specifically, member declarators of the forms

identifier
expr.identifier

は、それぞれ次のものに相当します。are precisely equivalent to the following, respectively:

identifier = identifier
identifier = expr.identifier

したがって、プロジェクション初期化子では、値が割り当てられる値とフィールドまたはプロパティの両方が 識別子 によって選択されます。Thus, in a projection initializer the identifier selects both the value and the field or property to which the value is assigned. 直感的に言えば、プロジェクション初期化子は、値だけでなく、値の名前でもあります。Intuitively, a projection initializer projects not just a value, but also the name of the value.

Typeof 演算子The typeof operator

typeof演算子は、型のオブジェクトを取得するために使用され System.Type ます。The typeof operator is used to obtain the System.Type object for a type.

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

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

generic_dimension_specifier
    : '<' comma* '>'
    ;

comma
    : ','
    ;

Typeof_expression の最初の形式は、キーワードとそれ typeof に続くかっこで囲まれた で構成されます。The first form of typeof_expression consists of a typeof keyword followed by a parenthesized type. この形式の式の結果は、指定された System.Type 型のオブジェクトになります。The result of an expression of this form is the System.Type object for the indicated type. System.Type特定の型に対してオブジェクトが1つだけ存在します。There is only one System.Type object for any given type. つまり、型の場合  Ttypeof(T) == typeof(T) は常に true になります。This means that for a type T, typeof(T) == typeof(T) is always true. をにすることはできません dynamicThe type cannot be dynamic.

2番目の形式の typeof_expression は、 typeof キーワードの後にかっこで囲んだ unbound_type_name で構成されます。The second form of typeof_expression consists of a typeof keyword followed by a parenthesized unbound_type_name. Unbound_type_nametype_name (名前空間と型名) と非常によく似ていますが、 type_nametype_argument_list が含まれる generic_dimension_specifierunbound_type_name に含まれている点が異なります。An unbound_type_name is very similar to a type_name (Namespace and type names) except that an unbound_type_name contains generic_dimension_specifier s where a type_name contains type_argument_list s. Typeof_expression のオペランドが unbound_type_nametype_name の両方の文法を満たすトークンのシーケンスである場合、つまり、 generic_dimension_specifiertype_argument_list も含まれていない場合、トークンのシーケンスは type_name と見なされます。When the operand of a typeof_expression is a sequence of tokens that satisfies the grammars of both unbound_type_name and type_name, namely when it contains neither a generic_dimension_specifier nor a type_argument_list, the sequence of tokens is considered to be a type_name. Unbound_type_name の意味は、次のように決定されます。The meaning of an unbound_type_name is determined as follows:

  • generic_dimension_specifier を同じ数のコンマと type_argument キーワードを持つ type_argument_list に置き換えることによって、トークンのシーケンスを type_name に変換し object ます。 Convert 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.

3番目の形式の typeof_expression は、 typeof キーワードの後にかっこで囲まれたキーワードで構成され void ます。The third form of typeof_expression consists of a typeof keyword followed by a parenthesized void keyword. この形式の式の結果は、型が System.Type 存在しないことを表すオブジェクトです。The result of an expression of this form is the System.Type object that represents the absence of a type. によって返される型オブジェクト typeof(void) は、任意の型に対して返される型オブジェクトとは異なります。The type object returned by typeof(void) is distinct from the type object returned for any type. この特殊な型オブジェクトは、言語のメソッドにリフレクションを許可するクラスライブラリで役立ちます。この場合、メソッドは、void メソッドを含むメソッドの戻り値の型をのインスタンスと共に表す方法を必要と System.Type します。This special type object is useful in class libraries that allow reflection onto methods in the language, where those methods wish to have a way to represent the return type of any method, including void methods, with an instance of System.Type.

演算子は、 typeof 型パラメーターで使用できます。The typeof operator can be used on a type parameter. 結果は、 System.Type 型パラメーターにバインドされたランタイム型のオブジェクトです。The result is the System.Type object for the run-time type that was bound to the type parameter. この演算子は、構築された typeof 型またはバインドされていないジェネリック型 (バインドおよびバインド解除された型) でも使用できます。The typeof operator can also be used on a constructed type or an unbound generic type (Bound and unbound types). バインドされてい System.Type ないジェネリック型のオブジェクトは、 System.Type インスタンスの型のオブジェクトと同じではありません。The System.Type object for an unbound generic type is not the same as the System.Type object of the instance type. インスタンス型は常に、実行時にクローズ構築型になります。そのため、オブジェクトは、使用されている System.Type ランタイム型引数に依存しますが、バインドされていないジェネリック型には型引数がありません。The instance type is always a closed constructed type at run-time so its System.Type object depends on the run-time type arguments in use, while the unbound generic type has no type arguments.

例を示します。The example

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();
    }
}

では、次の出力が生成されます。produces the following output:

System.Int32
System.Int32
System.String
System.Double[]
System.Void
System.Int32
X`1[System.Int32]
X`1[X`1[System.Int32]]
X`1[T]

との型は同じであることに注意して int System.Int32 ください。Note that int and System.Int32 are the same type.

また、の結果は typeof(X<>) 型引数に依存せず、の結果がになることに注意して typeof(X<T>) ください。Also note that the result of typeof(X<>) does not depend on the type argument but the result of typeof(X<T>) does.

checked 演算子と unchecked 演算子The checked and unchecked operators

checkedおよび演算子は、 unchecked 整数型の算術演算および変換の オーバーフローチェックコンテキスト を制御するために使用されます。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 コンテキストで含まれて checked いる式を評価し、 unchecked 演算子は 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_expression または unchecked_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 unchecked ステートメントおよびステートメント (checked ステートメントと unchecked ステートメント) を使用して制御することもできます。The overflow checking context can also be controlled through the checked and unchecked statements (The checked and unchecked statements).

次の操作は、 checked および演算子およびステートメントによって確立されたオーバーフローチェックコンテキストの影響を受け unchecked ます。The following operations are affected by the overflow checking context established by the checked and unchecked operators and statements:

上記のいずれかの操作によって、変換先の型で表現するには大きすぎる結果が生成された場合、演算が実行されるコンテキストによって結果の動作が制御されます。When one of the above operations produce a result that is too large to represent in the destination type, the context in which the operation is performed controls the resulting behavior:

  • コンテキストで checked は、操作が定数式 (定数式) の場合、コンパイル時エラーが発生します。In a checked context, if the operation is a constant expression (Constant expressions), a compile-time error occurs. それ以外の場合、実行時に操作が実行されると、 System.OverflowException がスローされます。Otherwise, 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.

または演算子やステートメントで囲まれていない非定数式 (実行時に評価される式) の場合 checked unchecked 、既定のオーバーフローチェックコンテキストは、 unchecked 外部要因 (コンパイラスイッチや実行環境の構成など) が評価のために呼び出されない限り発生し checked ます。For non-constant expressions (expressions that are evaluated at run-time) that are not enclosed by any checked or unchecked operators or statements, the default overflow checking context is unchecked unless external factors (such as compiler switches and execution environment configuration) call for checked evaluation.

定数式 (コンパイル時に完全に評価できる式) の場合、既定のオーバーフローチェックコンテキストは常に checked です。For constant expressions (expressions that can be fully evaluated at compile-time), the default overflow checking context is always checked. 定数式がコンテキストに明示的に配置されていない限り unchecked 、式のコンパイル時の評価中にオーバーフローが発生すると、常にコンパイル時エラーが発生します。Unless a constant expression is explicitly placed in an unchecked context, overflows that occur during the compile-time evaluation of the expression always cause compile-time errors.

匿名関数の本体は、 checked 匿名関数が発生するまたはコンテキストの影響を受けません uncheckedThe body of an anonymous function is not affected by checked or unchecked contexts in which the anonymous function occurs.

この例では、In the example

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

コンパイル時のエラーは報告されません。コンパイル時に式を評価することはできません。no compile-time errors are reported since neither of the expressions can be evaluated at compile-time. 実行時に、メソッドはを F スロー System.OverflowException し、メソッドは G -727379968 (範囲外の結果の下位32ビット) を返します。At run-time, the F method throws a System.OverflowException, and the G method returns -727379968 (the lower 32 bits of the out-of-range result). メソッドの動作は、 H コンパイルの既定のオーバーフローチェックコンテキストに依存しますが、またはと同じであるか、 F と同じ G です。The behavior of the H method depends on the default overflow checking context for the compilation, but it is either the same as F or the same as G.

この例では、In the example

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

式がコンテキストで評価されるので、で定数式を評価 F し、 H コンパイル時エラーを報告するときに発生するオーバーフローです checkedthe overflows that occur when evaluating the constant expressions in F and H cause compile-time errors to be reported because the expressions are evaluated in a checked context. の定数式を評価するときにもオーバーフローが発生し G ますが、評価はコンテキストで行われるため、 unchecked オーバーフローは報告されません。An overflow also occurs when evaluating the constant expression in G, but since the evaluation takes place in an unchecked context, the overflow is not reported.

checkedAnd 演算子は、 unchecked " ( " および "" トークンに含まれる操作のオーバーフローチェックコンテキストにのみ影響し ) ます。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));
    }
}

のの使用は、の checked F の評価には影響しません x * y Multiply 。そのため、 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.

演算子は、 unchecked 符号付き整数型の定数を16進表記で記述する場合に便利です。The unchecked operator is convenient when writing constants of the signed integral types in hexadecimal notation. 次に例を示します。For example:

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

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

上記の16進定数は、どちらも型 uint です。Both of the hexadecimal constants above are of type uint. 定数は範囲外であるため int 、演算子を使用しない場合、 unchecked はにキャストされ、 int コンパイル時エラーが発生します。Because the constants are outside the int range, without the unchecked operator, the casts to int would produce compile-time errors.

プログラマは、演算子およびステートメントを使用して、 checked unchecked いくつかの数値計算の特定の側面を制御できます。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. たとえば、2つの10進数を乗算すると、明示的なコンストラクト内であっても、常にオーバーフローで例外が発生し unchecked ます。For example, multiplying two decimals always results in an exception on overflow even within an explicitly unchecked construct. 同様に、2つの浮動小数点数を乗算しても、明示的なコンストラクト内であってもオーバーフローで例外が発生することはありません checkedSimilarly, 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

既定値の式は、型の既定値 (既定値) を取得するために使用されます。A default value expression is used to obtain the default value (Default values) of a type. 通常、型パラメーターには既定値式が使用されます。これは、型パラメーターが値型または参照型であるかどうかが不明な場合があるためです。Typically a default value expression is used for type parameters, since it may not be known if the type parameter is a value type or a reference type. ( null 型パラメーターが参照型であることがわかっている場合を除き、リテラルから型パラメーターへの変換は存在しません)。(No conversion exists from the null literal to a type parameter unless the type parameter is known to be a reference type.)

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

Default_value_expression が実行時に参照型に評価される場合、結果は null その型に変換されます。If the type in a default_value_expression evaluates at run-time to a reference type, the result is null converted to that type. Default_value_expression が実行時に値型に評価される場合、結果は Value_type の既定値 (既定のコンストラクター) になります。If the type in a default_value_expression evaluates at run-time to a value type, the result is the value_type's default value (Default constructors).

型が参照型または参照型であることがわかっている型パラメーター (型パラメーターの制約) の場合、 default_value_expression は定数式 (定数式) です。A default_value_expression is a constant expression (Constant expressions) if the type is a reference type or a type parameter that is known to be a reference type (Type parameter constraints). また、型が 、、、、、、、、、、、、、 sbyte byte short ushort int uint long ulong char float double decimal bool または任意の列挙型のいずれかの値型の場合、default_value_expression は定数式です。In addition, a default_value_expression is a constant expression if the type is one of the following value types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, or any enumeration type.

すべてのの表記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
    ;

文法的に言えば、 named_entity のオペランドは常に式です。Grammatically speaking, the named_entity operand is always an expression. nameofは予約されたキーワードではないため、名前の後には、単純な名前を呼び出すと、常に構文的にあいまいになり nameof ます。Because nameof is not a reserved keyword, a nameof expression is always syntactically ambiguous with an invocation of the simple name nameof. 互換性の理由により、名前の名前の参照 (簡易名) が成功した場合、 nameof 式は、呼び出しが有効であるかどうかに関係なく、 invocation_expression として扱われます。For compatibility reasons, if a name lookup (Simple names) of the name nameof succeeds, the expression is treated as an invocation_expression -- regardless of whether the invocation is legal. それ以外の場合は、 nameof_expression になります。Otherwise it is a nameof_expression.

Nameof_expressionnamed_entity の意味は、式として意味があります。つまり、 simple_namebase_access または member_access のいずれかになります。The 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.

メソッドグループに type_argument_list が指定されている named_entity は、コンパイル時にエラーになります。It is a compile-time error for a named_entity designating a method group to have a type_argument_list. Named_entity_target が型を持つ場合、コンパイル時エラーになり dynamic ます。It is a compile time error for a named_entity_target to have the type dynamic.

Nameof_expression は型の定数式であり、 string 実行時には効果がありません。A nameof_expression is a constant expression of type string, and has no effect at runtime. 具体的には、その named_entity は評価されず、明確な代入分析 (単純式の一般的な規則) のために無視されます。Specifically, its named_entity is not evaluated, and is ignored for the purposes of definite assignment analysis (General rules for simple expressions). この値は、省略可能な最終 type_argument_list の前の named_entity の最後の識別子で、次のように変換されます。Its value is the last identifier of the named_entity before the optional final type_argument_list, transformed in the following way:

  • プレフィックス " @ " (使用されている場合) は削除されます。The prefix "@", if used, is removed.
  • unicode_escape_sequence は、対応する unicode 文字に変換されます。Each unicode_escape_sequence is transformed into its corresponding Unicode character.
  • Formatting_characters はすべて削除されます。Any formatting_characters are removed.

これらは、識別子が等しいかどうかをテストするときに 識別子 に適用される変換と同じです。These are the same transformations applied in Identifiers when testing equality between identifiers.

TODO: 例TODO: examples

匿名メソッドの式Anonymous method expressions

Anonymous_method_expression は、匿名関数を定義する2つの方法のうちの1つです。An anonymous_method_expression is one of two ways of defining an anonymous function. これらの詳細については、「 匿名関数の式」を参照してください。These are further described in Anonymous function expressions.

単項演算子Unary operators

?、、 + 、、、、 - ! ~ ++ -- 、Cast、およびの各 await 演算子は、単項演算子と呼ばれます。The ?, +, -, !, ~, ++, --, cast, and await operators are called the unary operators.

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

Unary_expression のオペランドにコンパイル時の型がある場合 dynamic 、そのオペランドは動的にバインドされます (動的バインド)。If the operand of a unary_expression has the compile-time type dynamic, it is dynamically bound (Dynamic binding). この場合、 unary_expression のコンパイル時の型はであり、以下に示す解決方法は、実行時 dynamic にオペランドの実行時の型を使用して行われます。In this case the compile-time type of the unary_expression is dynamic, and the resolution described below will take place at run-time using the run-time type of the operand.

NULL 条件演算子Null-conditional operator

Null 条件演算子では、オペランドが null 以外の場合にのみ、演算のリストがオペランドに適用されます。The null-conditional operator applies a list of operations to its operand only if that operand is non-null. それ以外の場合は、演算子を適用した結果がになり null ます。Otherwise the result of applying the operator is null.

null_conditional_expression
    : primary_expression null_conditional_operations
    ;

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

操作の一覧には、メンバーアクセスと要素アクセス操作 (それ自体が null 条件の場合もあります)、および呼び出しを含めることができます。The list of operations can include member access and element access operations (which may themselves be null-conditional), as well as invocation.

たとえば、式は、 a.b?[0]?.c() primary_expression a.bnull_conditional_operations ?[0] (null 条件付きの要素アクセス)、(null 条件付き ?.c のメンバーアクセス)、 () (呼び出し) を含む null_conditional_expression です。For example, the expression a.b?[0]?.c() is a null_conditional_expression with a primary_expression a.b and null_conditional_operations ?[0] (null-conditional element access), ?.c (null-conditional member access) and () (invocation).

Primary_expression を持つ null_conditional_expression につい E ては、を使用して、 P E0 の各 null_conditional_operations の先頭を削除することによって得られる式に ? E します。For a null_conditional_expression E with a primary_expression P, let E0 be the expression obtained by textually removing the leading ? from each of the null_conditional_operations of E that have one. 概念的に E0 は、によって表される null チェックでが見つからない場合に評価される式です ? nullConceptually, E0 is the expression that will be evaluated if none of the null checks represented by the ?s do find a null.

また、の E1 最初の null_conditional_operations から先頭を削除することによって得られる式を ?E します。Also, let E1 be the expression obtained by textually removing the leading ? from just the first of the null_conditional_operations in E. これに より、プライマリ式 (ある場合 ? ) または別の null_conditional_expression が発生する可能性があります。This may lead to a primary-expression (if there was just one ?) or to another null_conditional_expression.

たとえば、が式の場合、は式で、は式 E a.b?[0]?.c() E0 a.b[0].c() E1 a.b[0]?.c() です。For example, if E is the expression a.b?[0]?.c(), then E0 is the expression a.b[0].c() and E1 is the expression a.b[0]?.c().

E0が nothing として分類されている場合、 E は nothing として分類されます。If E0 is classified as nothing, then E is classified as nothing. それ以外の場合、E は値として分類されます。Otherwise E is classified as a value.

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 は1回だけ評価されます。except that P is evaluated only once.

  • それ以外の場合、 E0 がに分類されていても、コンパイル時エラーが発生します。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 は1回だけ評価されます。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 は1回だけ評価されます。except that P is evaluated only once.

E1がそれ自体が null_conditional_expression である場合、これらの規則が再度適用され、それ以上のが存在しない場合はのテストが入れ子に null なり、式は ? すべてプライマリ式まで縮小され E0 ます。If E1 is itself a null_conditional_expression, then these rules are applied again, nesting the tests for null until there are no further ?'s, and the expression has been reduced all the way down to the primary-expression E0.

たとえば、次のステートメントのように、式が a.b?[0]?.c() ステートメント式として出現する場合は、次のようになります。For example, if the expression a.b?[0]?.c() occurs as a statement-expression, as in the statement:

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

その意味は、次の場合と同じです。its meaning is equivalent to:

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

これは、次の場合と同じです。which again is equivalent to:

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

a.bとは、 a.b[0] 1 回だけ評価される点が異なります。Except that a.b and a.b[0] are evaluated only once.

次のように、その値が使用されているコンテキストで発生する場合:If it occurs in a context where its value is used, as in:

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

最後の呼び出しの型が null 非許容の値型ではないと仮定した場合、その意味は次のようになります。and assuming that the type of the final invocation is not a non-nullable value type, its meaning is equivalent to:

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

a.bとは、 a.b[0] 1 回だけ評価される点が異なります。except that a.b and a.b[0] are evaluated only once.

Null 条件式 (プロジェクション初期化子としての)Null-conditional expressions as projection initializers

Null 条件式は、(必要に応じて null 条件付き) メンバーアクセスで終了する場合にのみ、 anonymous_object_creation_expression (匿名オブジェクト作成式) の member_declarator としてのみ使用できます。A null-conditional expression is only allowed as a member_declarator in an anonymous_object_creation_expression (Anonymous object creation expressions) if it ends with an (optionally null-conditional) member access. 文法的には、この要件は次のように表現できます。Grammatically, this requirement can be expressed as:

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

これは、上記の null_conditional_expression の文法の特殊なケースです。This is a special case of the grammar for null_conditional_expression above. 匿名オブジェクト作成式member_declarator の実稼働には、 null_conditional_member_access のみが含まれます。The production for member_declarator in Anonymous object creation expressions then includes only null_conditional_member_access.

ステートメント式としての Null 条件式Null-conditional expressions as statement expressions

Null 条件式は、呼び出しで終了した場合にのみ statement_expression (式ステートメント) として使用できます。A null-conditional expression is only allowed as a statement_expression (Expression statements) if it ends with an invocation. 文法的には、この要件は次のように表現できます。Grammatically, this requirement can be expressed as:

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

これは、上記の null_conditional_expression の文法の特殊なケースです。This is a special case of the grammar for null_conditional_expression above. 式ステートメント内の statement_expression の実稼働には、 null_conditional_invocation_expression のみが含まれます。The production for statement_expression in Expression statements then includes only null_conditional_invocation_expression.

単項プラス演算子Unary plus operator

フォームの操作で +x は、単項演算子のオーバーロードの解決 (単項演算子のオーバーロードの解決) を適用して、特定の演算子の実装を選択します。For an operation of the form +x, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択された演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. 定義済みの単項プラス演算子は次のとおりです。The predefined unary plus operators are:

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);

これらの各演算子について、結果は単純にオペランドの値になります。For each of these operators, the result is simply the value of the operand.

単項マイナス演算子Unary minus operator

フォームの操作で -x は、単項演算子のオーバーロードの解決 (単項演算子のオーバーロードの解決) を適用して、特定の演算子の実装を選択します。For an operation of the form -x, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択された演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. 定義済みの否定演算子は次のとおりです。The predefined negation operators are:

  • 整数の否定:Integer negation:

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

    結果は0から減算することによって計算され x ます。The result is computed by subtracting x from zero. の値が、 x オペランドの型の最も小さい表現可能な値 (の場合は-2 ^ 31、の場合 int は-2 ^ 63) の場合 long 、の算術否定 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) を10進整数リテラル (整数リテラル) として書き込むことを許可するルールです。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) を10進整数リテラル (整数リテラル) として書き込むことを許可するルールです。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.

  • 10進数の否定:Decimal negation:

    decimal operator -(decimal x);
    

    結果は0から減算することによって計算され x ます。The result is computed by subtracting x from zero. 10進数の否定は、型の単項マイナス演算子を使用することと同じです System.DecimalDecimal negation is equivalent to using the unary minus operator of type System.Decimal.

論理否定演算子Logical negation operator

フォームの操作で !x は、単項演算子のオーバーロードの解決 (単項演算子のオーバーロードの解決) を適用して、特定の演算子の実装を選択します。For an operation of the form !x, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択された演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. 定義済みの論理否定演算子は1つだけ存在します。Only one predefined logical negation operator exists:

bool operator !(bool x);

この演算子は、オペランドの論理否定を計算します。オペランドがの場合 true 、結果はに false なります。This operator computes the logical negation of the operand: If the operand is true, the result is false. オペランドが false の場合、結果は true になります。If the operand is false, the result is true.

ビットごとの補数演算子Bitwise complement operator

フォームの操作で ~x は、単項演算子のオーバーロードの解決 (単項演算子のオーバーロードの解決) を適用して、特定の演算子の実装を選択します。For an operation of the form ~x, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択された演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. 定義済みのビットごとの補数演算子は次のとおりです。The predefined bitwise complement operators are:

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

これらの各演算子について、演算の結果はのビットごとの補数になり x ます。For each of these operators, the result of the operation is the bitwise complement of x.

すべての列挙型 E は、暗黙的に次のビットごとの補数演算子を提供します。Every enumeration type E implicitly provides the following bitwise complement operator:

E operator ~(E x);

を評価した結果、 ~x x は、基になる型を持つ列挙型の式であり、を評価するの E U とまったく同じです (E)(~(U)x) 。ただし、への変換は、常に E unchecked コンテキスト (checked および unchecked 演算子) の場合と同じように実行されます。The result of evaluating ~x, where x is an expression of an enumeration type E with an underlying type U, is exactly the same as evaluating (E)(~(U)x), except that the conversion to E is always performed as if in an unchecked context (The checked and unchecked operators).

前置インクリメント演算子と前置デクリメント演算子Prefix increment and decrement operators

pre_increment_expression
    : '++' unary_expression
    ;

pre_decrement_expression
    : '--' unary_expression
    ;

前置インクリメントまたはデクリメント演算のオペランドは、変数、プロパティアクセス、またはインデクサーアクセスとして分類される式である必要があります。The operand of a prefix increment or decrement operation must be an expression classified as a variable, a property access, or an indexer access. 演算の結果は、オペランドと同じ型の値になります。The result of the operation is a value of the same type as the operand.

前置インクリメントまたはデクリメント演算のオペランドがプロパティまたはインデクサーアクセスである場合、プロパティまたはインデクサーにアクセサーとアクセサーの両方が必要 get set です。If the operand of a prefix increment or decrement operation is a property or indexer access, the property or indexer must have both a get and a set accessor. そうでない場合は、バインド時エラーが発生します。If this is not the case, a binding-time error occurs.

単項演算子のオーバーロードの解決 (単項演算子のオーバーロードの解決) は、特定の演算子の実装を選択するために適用されます。Unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. 、、、、、、、、、、、、およびの各 ++ -- sbyte byte short ushort int uint long ulong char float double decimal 列挙型には、定義済みの演算子と演算子が存在します。Predefined ++ and -- operators exist for the following types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, and any enum type. 定義済みの演算子は、 ++ オペランドに1を加算して生成された値を返します。定義済みの演算子は、 -- オペランドから1を減算して生成された値を返します。The predefined ++ operators return the value produced by adding 1 to the operand, and the predefined -- operators return the value produced by subtracting 1 from the operand. コンテキストで checked 、この加算または減算の結果が結果型の範囲外で、結果型が整数型または列挙型である場合、 System.OverflowException がスローされます。In a checked context, if the result of this addition or subtraction is outside the range of the result type and the result type is an integral type or enum type, a System.OverflowException is thrown.

フォームまたはのプレフィックスインクリメントまたはデクリメント操作の実行時の処理は、 ++x --x 次の手順で構成されます。The run-time processing of a prefix increment or decrement operation of the form ++x or --x consists of the following steps:

  • xが変数として分類される場合は、次のようになります。If x is classified as a variable:
    • x は、変数を生成するために評価されます。x is evaluated to produce the variable.
    • 選択した演算子は、引数としての値を使用して呼び出され x ます。The selected operator is invoked with the value of x as its argument.
    • 演算子によって返される値は、の評価によって指定された場所に格納され x ます。The value returned by the operator is stored in the location given by the evaluation of x.
    • 演算子によって返される値は、操作の結果になります。The value returned by the operator becomes the result of the operation.
  • xがプロパティまたはインデクサーアクセスとして分類される場合は、次のようになります。If x is classified as a property or indexer access:
    • インスタンス式 (がで x はない場合) static およびに関連付けられた引数リスト ( x がインデクサーアクセスの場合) x が評価され、その結果が後続のおよびアクセサー呼び出しで使用され get 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 get and set accessor invocations.
    • getのアクセサー x が呼び出されます。The get accessor of x is invoked.
    • 選択した演算子は、引数としてアクセサーによって返された値を使用して呼び出され get ます。The selected operator is invoked with the value returned by the get accessor as its argument.
    • setのアクセサー x は、演算子によって返された値を引数として使用して呼び出され value ます。The set accessor of x is invoked with the value returned by the operator as its value argument.
    • 演算子によって返される値は、操作の結果になります。The value returned by the operator becomes the result of the operation.

++および演算子は、 -- 後置表記 (後置インクリメントおよびデクリメント演算子) もサポートしています。The ++ and -- operators also support postfix notation (Postfix increment and decrement operators). 通常、またはの結果は x++ x-- 演算の前のの値ですが、 x またはの結果は ++x --x 操作後のの値になり x ます。Typically, the result of x++ or x-- is the value of x before the operation, whereas the result of ++x or --x is the value of x after the operation. どちらの場合も、 x 操作後の値は同じになります。In either case, x itself has the same value after the operation.

operator++またはの実装は、 operator-- 後置表記またはプレフィックス表記のいずれかを使用して呼び出すことができます。An operator++ or operator-- implementation can be invoked using either postfix or prefix notation. 2つの表記に対して個別の演算子を実装することはできません。It is not possible to have separate operator implementations for the two notations.

キャスト式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 ( (T)E T、は unary_expression であり E 、は型への値の明示的な変換 (明示的な変換) を実行し E T ます。A cast_expression of the form (T)E, where T is a type and E is a unary_expression, performs an explicit conversion (Explicit conversions) of the value of E to type T. からへの明示的な変換が存在しない場合 E T 、バインディング時エラーが発生します。If no explicit conversion exists from E to T, a binding-time error occurs. それ以外の場合、結果は明示的な変換によって生成される値になります。Otherwise, the result is the value produced by the explicit conversion. が変数を表している場合でも、結果は常に値として分類され E ます。The result is always classified as a value, even if E denotes a variable.

Cast_expression の文法によって、特定の構文のあいまいさが生じます。The grammar for a cast_expression leads to certain syntactic ambiguities. たとえば、式は (x)-y cast_expression として解釈するか (型へのキャスト -y )、 x additive_expression として parenthesized_expression (値を計算する) として解釈することができ x - y) ます。For example, the expression (x)-y could either be interpreted as a cast_expression (a cast of -y to type x) or as an additive_expression combined with a parenthesized_expression (which computes the value x - y).

Cast_expression のあいまいさを解決するために、次の規則が存在します。かっこで囲まれた1つ以上の トークン s (空白) のシーケンスは、次のいずれかが true の場合にのみ、 cast_expression の開始と見なされます。To resolve cast_expression ambiguities, the following rule exists: A sequence of one or more token s (White space) enclosed in parentheses is considered the start of a cast_expression only if at least one of the following are true:

  • トークンのシーケンスは、 の正しい文法ですが、 には対応していません。The sequence of tokens is correct grammar for a type, but not for an expression.
  • トークンのシーケンスは、 の正しい文法です。閉じかっこの直後にあるトークンは、トークン " ~ "、トークン ""、トークン ! ""、 ( 識別子 (Unicode 文字のエスケープシーケンス)、 リテラル (リテラル)、またはとを除く任意の キーワード (キーワード) as です isThe 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.

上記の "正しい文法" という用語は、トークンのシーケンスが、特定の文章の作成に準拠している必要があることを意味します。The term "correct grammar" above means only that the sequence of tokens must conform to the particular grammatical production. 具体的には、構成要素の実際の意味は考慮されません。It specifically does not consider the actual meaning of any constituent identifiers. たとえば、とが識別子の場合、は、 x y 実際に x.y 型を表していない場合でも、型の正しい文法です x.yFor example, if x and y are identifiers, then x.y is correct grammar for a type, even if x.y doesn't actually denote a type.

xy が識別子、、、cast_expression およびがである場合、 (x)y(x)(y) (x)(-y) (x)-y 型を識別する場合でも x 、あいまいさのルールから次のようになります。From the disambiguation rule it follows that, if x and y are identifiers, (x)y, (x)(y), and (x)(-y) are cast_expression s, but (x)-y is not, even if x identifies a type. ただし、 x が定義済みの型 (など) を識別するキーワードの場合、 int 4 つのすべての形式は cast_expression s になります (そのようなキーワードは、それ自体が式になるとは限りません)。However, if x is a keyword that identifies a predefined type (such as int), then all four forms are cast_expression s (because such a keyword could not possibly be an expression by itself).

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
    ;

Await_expression は、非同期関数の本体 (非同期関数) でのみ使用できます。An await_expression is only allowed in the body of an async function (Async functions). 最も近い外側の非同期関数内では、次の場所では await_expression が発生しない可能性があります。Within the nearest enclosing async function, an await_expression may not occur in these places:

  • 入れ子になった (非同期ではない) 匿名関数内Inside a nested (non-async) anonymous function
  • Lock_statement のブロック内Inside the block of a lock_statement
  • Unsafe コンテキスト内In an unsafe context

Await_expression は、非同期のラムダ式を使用するように構文的に変換されるため、 query_expression 内のほとんどの場所では発生しないことに注意してください。Note that an await_expression cannot occur in most places within a query_expression, because those are syntactically transformed to use non-async lambda expressions.

非同期関数内では、を await 識別子として使用することはできません。Inside of an async function, await cannot be used as an identifier. したがって、await 式と、識別子を含むさまざまな式の間に構文のあいまいさはありません。There is therefore no syntactic ambiguity between await-expressions and various expressions involving identifiers. 非同期関数の外部では、は await 通常の識別子として機能します。Outside of async functions, await acts as a normal identifier.

Await_expression のオペランドは、*task _ と呼ばれます。The operand of an await_expression is called the *task _. これは、_await_expression * の評価時に完了しない可能性のある非同期操作を表します。It represents an asynchronous operation that may or may not be complete at the time the _await_expression* is evaluated. Await 演算子の目的は、待機中のタスクが完了するまで、外側の非同期関数の実行を中断し、その結果を取得することです。The purpose of the await operator is to suspend execution of the enclosing async function until the awaited task is complete, and then obtain its outcome.

待機可能式Awaitable expressions

Await 式のタスクは、 待機可能 である必要があります。The task of an await expression is required to be awaitable. 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 (これ INotifyCompletion は、簡潔にするために知られています)。A 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には、パラメーターのないアクセス可能なインスタンスメソッドと、型パラメーターがありません。 GetResultA has an accessible instance method GetResult with no parameters and no type parameters

メソッドの目的は、 GetAwaiter タスクの *awaiter _ を取得することです。The purpose of the GetAwaiter method is to obtain an *awaiter _ for the task. この型 A は、await 式の _ awaiter type* と呼ばれます。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 式の分類Classification of await expressions

await t は、式と同じ方法で分類され (t).GetAwaiter().GetResult() ます。The expression await t is classified the same way as the expression (t).GetAwaiter().GetResult(). したがって、の戻り値の型がの場合、 GetResult void await_expression は nothing として分類されます。Thus, if the return type of GetResult is void, the await_expression is classified as nothing. Void 以外の戻り値の型がある場合 Tawait_expression は型の値として分類され T ます。If it has a non-void return type T, the await_expression is classified as a value of type T.

Await 式のランタイム評価Runtime evaluation of await expressions

実行時、式は次のように await t 評価されます。At runtime, the expression await t is evaluated as follows:

  • Awaiter a は、式を評価することによって取得 (t).GetAwaiter() します。An awaiter a is obtained by evaluating the expression (t).GetAwaiter().
  • は、 bool b 式を評価することによって取得され (a).IsCompleted ます。A bool b is obtained by evaluating the expression (a).IsCompleted.
  • bがの場合 false 、はインターフェイスを実装するかどうかによっ 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 コンパイル時になります。 dynamicThis 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 (Async functions):
    • 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.
    • その後、評価は中断され、非同期関数の現在の呼び出し元に制御が返されます。Evaluation is then suspended, and control is returned to the current caller of the async function.
  • の直後 ( b がの場合 true )、または後で再開デリゲートを呼び出したとき ( 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.OnCompleted より、 ICriticalNotifyCompletion.UnsafeOnCompleted デリゲートは r 最大で1回呼び出す必要があります。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
    ;

additive_expression
    : multiplicative_expression
    | additive_expression '+' multiplicative_expression
    | additive_expression '-' multiplicative_expression
    ;

算術演算子のオペランドにコンパイル時の型がある場合 dynamic 、式は動的にバインドされます (動的バインド)。If an operand of an arithmetic operator has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). この場合、式のコンパイル時の型はであり、 dynamic 以下に示す解決方法は、コンパイル時の型を持つオペランドの実行時の型を使用して実行時に行われ dynamic ます。In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

乗算演算子Multiplication operator

フォームの操作では x * y 、二項演算子のオーバーロードの解決 (二項演算子のオーバーロードの解決) を適用して、特定の演算子の実装を選択します。For an operation of the form x * y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択した演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

定義済みの乗算演算子を以下に示します。The predefined multiplication operators are listed below. すべての演算子は、との積を計算し x y ます。The operators all compute the product of x and y.

  • 整数乗算: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.OverflowException がスローされます。In 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. 次の表に、0 以外の有限値、0、無限大、および 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 は 0 です。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
  • 10進数の乗算:Decimal multiplication:

    decimal operator *(decimal x, decimal y);
    

    結果の値が大きすぎて形式で表現できない場合は、 decimal System.OverflowException がスローされます。If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 結果値が小さすぎて形式で表現できない場合、結果は0になり decimal ます。If the result value is too small to represent in the decimal format, the result is zero. 結果の小数点以下桁数は、2つのオペランドのスケールの合計になります。The scale of the result, before any rounding, is the sum of the scales of the two operands.

    Decimal 型の乗算は、型の乗算演算子を使用することと同じです System.DecimalDecimal multiplication is equivalent to using the multiplication operator of type System.Decimal.

除算演算子Division operator

フォームの操作では x / y 、二項演算子のオーバーロードの解決 (二項演算子のオーバーロードの解決) を適用して、特定の演算子の実装を選択します。For an operation of the form x / y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択した演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

定義済みの除算演算子を以下に示します。The predefined division operators are listed below. すべての演算子は、との商を計算し x y ます。The operators all compute the quotient of x and y.

  • 整数除算: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);
    

    右オペランドの値が0の場合は、 System.DivideByZeroException がスローされます。If the value of the right operand is zero, a System.DivideByZeroException is thrown.

    除算は、結果を0方向に丸めます。The division rounds the result towards zero. したがって、結果の絶対値は、2つのオペランドの商の絶対値以下の最大の整数になります。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. 2つのオペランドの符号が逆の場合、結果は0または正になります。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.

    左側のオペランドが表現可能な最小 int 値または値で、 long 右オペランドがの場合は -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. 次の表に、0 以外の有限値、0、無限大、および 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 は 0 です。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);
    

    右オペランドの値が0の場合は、 System.DivideByZeroException がスローされます。If the value of the right operand is zero, a System.DivideByZeroException is thrown. 結果の値が大きすぎて形式で表現できない場合は、 decimal System.OverflowException がスローされます。If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 結果値が小さすぎて形式で表現できない場合、結果は0になり decimal ます。If the result value is too small to represent in the decimal format, the result is zero. 結果の小数点以下桁数は、実際の数値の結果に最も近い表現可能な10進値と等しい結果を保持する最小のスケールになります。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.DecimalDecimal division is equivalent to using the division operator of type System.Decimal.

剰余演算子Remainder operator

フォームの操作では x % y 、二項演算子のオーバーロードの解決 (二項演算子のオーバーロードの解決) を適用して、特定の演算子の実装を選択します。For an operation of the form x % y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択した演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

定義済みの剰余演算子を次に示します。The predefined remainder operators are listed below. すべての演算子は、との間の除算の剰余を計算し x y ます。The operators all compute the remainder of the division between x and y.

  • 整数の剰余: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) * yThe result of x % y is the value produced by x - (x / y) * y. が0の場合は、が y System.DivideByZeroException スローされます。If y is zero, a System.DivideByZeroException is thrown.

    左側のオペランドが最小値または値で、右オペランドがの場合は、 int long -1 System.OverflowException がスローされます。If the left operand is the smallest int or long value and the right operand is -1, a System.OverflowException is thrown. で例外がスロー x % y されない場合、は例外をスローしません x / yIn 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);
    

    次の表に、0 以外の有限値、0、無限大、および 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. z はの結果であり x % y 、はとして計算され x - n * y ます。ここで、 n は、以下の最大の整数です x / yz 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
  • 10進数の剰余:Decimal remainder:

    decimal operator %(decimal x, decimal y);
    

    右オペランドの値が0の場合は、 System.DivideByZeroException がスローされます。If the value of the right operand is zero, a System.DivideByZeroException is thrown. 結果の小数点以下桁数は、丸め処理の前に2つのオペランドのスケールのうち、大きい方になります。0以外の場合、結果の符号はと同じになり 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.

    Decimal 剰余は、型の剰余演算子を使用することと同じです System.DecimalDecimal remainder is equivalent to using the remainder operator of type System.Decimal.

加算演算子Addition operator

フォームの操作では x + y 、二項演算子のオーバーロードの解決 (二項演算子のオーバーロードの解決) を適用して、特定の演算子の実装を選択します。For an operation of the form x + y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択した演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

定義済みの加算演算子を以下に示します。The predefined addition operators are listed below. 数値型と列挙型の場合、定義済みの加算演算子は、2つのオペランドの合計を計算します。For numeric and enumeration types, the predefined addition operators compute the sum of the two operands. 一方または両方のオペランドが string 型の場合、定義済みの加算演算子は、オペランドの文字列形式を連結します。When one or both operands are of type string, the predefined addition operators concatenate the string representation of the operands.

  • 整数加算:Integer addition:

    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.OverflowException がスローされます。In 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.

  • 浮動小数点加算:Floating-point addition:

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

    合計は、IEEE 754 算術のルールに従って計算されます。The sum is computed according to the rules of IEEE 754 arithmetic. 次の表に、0 以外の有限値、0、無限大、および NaN のすべての可能な組み合わせの結果を示します。The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. この表では、xy は 0 以外の有限値であり、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 + yIf 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 addition:

    decimal operator +(decimal x, decimal y);
    

    結果の値が大きすぎて形式で表現できない場合は、 decimal System.OverflowException がスローされます。If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 結果の小数点以下の桁数は、2つのオペランドのスケールのうち、大きい方になります。The scale of the result, before any rounding, is the larger of the scales of the two operands.

    Decimal 加算は、型の加算演算子を使用することと同じです System.DecimalDecimal addition is equivalent to using the addition operator of type System.Decimal.

  • 列挙型の追加。Enumeration addition. すべての列挙型は、暗黙的に次の定義済み演算子を提供します。ここで、 E は列挙型で U あり、はの基になる型です EEvery 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. それ以外の場合は、型から継承された仮想メソッドを呼び出すことによって、文字列以外の引数が文字列形式に変換され ToString object ます。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
        }
    }
    

    文字列連結演算子の結果は、左オペランドの文字と右オペランドの文字で構成される文字列です。 文字列連結演算子は、値を返しません nullSystem.OutOfMemoryException結果の文字列を割り当てるのに十分なメモリがない場合は、がスローされる可能性があります。A 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 、演算の結果は2番目のオペランドの値になります (その場合も 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). それ以外の場合、2番目のオペランドがの場合、 null 演算の結果は最初のオペランドの値になります。Otherwise, if the second operand is null, then the result of the operation is the value of the first operand. それ以外の場合、操作の結果は新しいデリゲートインスタンスになり、呼び出されると、最初のオペランドが呼び出され、2番目のオペランドが呼び出されます。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

フォームの操作では x - y 、二項演算子のオーバーロードの解決 (二項演算子のオーバーロードの解決) を適用して、特定の演算子の実装を選択します。For an operation of the form x - y, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択した演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

次に、定義済みの減算演算子を示します。The predefined subtraction operators are listed below. 演算子はすべてから減算され y x ます。The operators all subtract y from x.

  • 整数の減算: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.OverflowException がスローされます。In 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. 次の表に、0以外の有限値、ゼロ、無限大、および Nan のすべての可能な組み合わせの結果を示します。The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaNs. この表では、xy は 0 以外の有限値であり、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 - yIf 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
  • 10進数の減算:Decimal subtraction:

    decimal operator -(decimal x, decimal y);
    

    結果の値が大きすぎて形式で表現できない場合は、 decimal System.OverflowException がスローされます。If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. 結果の小数点以下の桁数は、2つのオペランドのスケールのうち、大きい方になります。The scale of the result, before any rounding, is the larger of the scales of the two operands.

    Decimal 減算は、型の減算演算子を使用することと同じです System.DecimalDecimal subtraction is equivalent to using the subtraction operator of type System.Decimal.

  • 列挙型の減算。Enumeration subtraction. すべての列挙型は、暗黙的に次の定義済み演算子を提供します。ここで、 E は列挙型で U あり、はの基になる型です EEvery 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 の場合は、演算結果は null になります。If the first operand is null, the result of the operation is null. それ以外の場合、2番目のオペランドがの場合、 null 演算の結果は最初のオペランドの値になります。Otherwise, if the second operand is null, then the result of the operation is the value of the first operand. それ以外の場合、どちらのオペランドも1つ以上のエントリを持つ呼び出しリスト (デリゲート宣言) を表します。結果は、2番目のオペランドのリストが最初ののサブリストである場合に、2番目のオペランドのエントリが削除された最初のオペランドリストで構成される新しい呼び出しリストになります。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. 2番目のオペランドのリストが、最初のオペランドのリスト内の連続するエントリの複数のサブリストと一致する場合、連続するエントリの右側に一致するサブリストが削除されます。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. 削除によりリストが空になる場合、結果は null になります。If 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
    : additive_expression
    | shift_expression '<<' additive_expression
    | shift_expression right_shift additive_expression
    ;

Shift_expression のオペランドにコンパイル時の型がある場合 dynamic 、式は動的にバインドされます (動的バインド)。If an operand of a shift_expression has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). この場合、式のコンパイル時の型はであり、 dynamic 以下に示す解決方法は、コンパイル時の型を持つオペランドの実行時の型を使用して実行時に行われ dynamic ます。In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

またはの形式の操作で x << countx >> count 、二項演算子のオーバーロードの解決 (二項演算子のオーバーロードの解決) が適用され、特定の演算子の実装を選択します。For an operation of the form x << count or x >> count, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択した演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

オーバーロードされたシフト演算子を宣言する場合、最初のオペランドの型は、常に演算子宣言を含むクラスまたは構造体である必要があり、2番目のオペランドの型は常にである必要があり int ます。When declaring an overloaded shift operator, the type of the first operand must always be the class or struct containing the operator declaration, and the type of the second operand must always be int.

次に、定義済みのシフト演算子を示します。The predefined shift operators are listed below.

  • 左シフト: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 は破棄され、残りのビットは左にシフトされ、下位の空のビット位置は0に設定されます。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 int 上位の空の long x ビット位置が0に設定され x x ます。When x is of type int or long, the low-order bits of x are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero if x is non-negative and set to one if x is negative.

    x 型が uint またはの場合 ulong 、の下位ビットは x 破棄され、残りのビットは右にシフトされ、上位の空のビット位置は0に設定されます。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.

定義済みの演算子の場合、シフトするビット数は次のように計算されます。For the predefined operators, the number of bits to shift is computed as follows:

  • の型 xint またはの場合 uint 、シフト数はの下位5ビットによって指定され count ます。When the type of x is int or uint, the shift count is given by the low-order five bits of count. つまり、シフト数はから計算され count & 0x1F ます。In other words, the shift count is computed from count & 0x1F.
  • の型 xlong またはの場合 ulong 、シフト数はの下位6ビットによって指定され 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.

結果として得られるシフト数が0の場合、シフト演算子は単にの値を返し x ます。If the resulting shift count is zero, the shift operators simply return the value of x.

シフト操作ではオーバーフローが発生することはなく、コンテキストでも同じ結果が生成さ checked unchecked れます。Shift operations never cause overflows and produce the same results in checked and unchecked contexts.

演算子の左オペランド >> が符号付き整数型の場合、演算子は、オペランドの最上位ビット (符号ビット) の値が上位の空のビット位置に反映されるように、算術シフト権限を実行します。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. 演算子の左オペランド >> が符号なし整数型の場合、演算子は論理シフト右を実行します。上位の空のビット位置は常に0に設定されます。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. たとえば、 x が型の変数である場合、 int 操作は 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

==、、 != < 、、、 > 、およびの各 <= >= is as 演算子は、関係演算子と型検査演算子と呼ばれます。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.

比較演算子のオペランドにコンパイル時の型がある場合 dynamic 、式は動的にバインドされます (動的バインド)。If an operand of a comparison operator has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). この場合、式のコンパイル時の型はであり、 dynamic 以下に示す解決方法は、コンパイル時の型を持つオペランドの実行時の型を使用して実行時に行われ dynamic ます。In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

Op という形式の操作で x y は、 op は比較演算子で、オーバーロードの解決 (二項演算子のオーバーロードの解決) が適用され、特定の演算子の実装を選択します。For an operation of the form x op y, where op is a comparison operator, overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択した演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

定義済みの比較演算子については、次のセクションで説明します。The predefined comparison operators are described in the following sections. 次の表に示すように、定義済みの比較演算子はすべて、型の結果を返し bool ます。All predefined comparison operators return a result of type bool, as described in the following table.

操作Operation 結果Result
x == y true``xがに等しい場合は。 y false それ以外の場合は。true if x is equal to y, false otherwise
x != y true``xがと等しくない場合は。 y false それ以外の場合は。true if x is not equal to y, false otherwise
x < y xy より小さい場合は true、それ以外の場合は falsetrue if x is less than y, false otherwise
x > y xy より大きい場合は true、それ以外の場合は falsetrue if x is greater than y, false otherwise
x <= y xy 以下の場合は true、それ以外の場合は falsetrue if x is less than or equal to y, false otherwise
x >= y xy 以上の場合は true、それ以外の場合は falsetrue if x is greater than or equal to y, false otherwise

整数の比較演算子Integer comparison operators

定義済みの整数の比較演算子は次のとおりです。The predefined integer comparison operators are:

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);

これらの各演算子は、2つの整数オペランドの数値を比較し、 bool 特定の関係がまたはであるかどうかを示す値を返し true false ます。Each of these operators compares the numeric values of the two integer operands and returns a bool value that indicates whether the particular relation is true or false.

浮動小数点比較演算子Floating-point comparison operators

定義済みの浮動小数点比較演算子は次のとおりです。The predefined floating-point comparison operators are:

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);

演算子は、IEEE 754 標準の規則に従って、オペランドを比較します。The operators compare the operands according to the rules of the IEEE 754 standard:

  • どちらかのオペランドが NaN の場合、結果は、 false を除くすべての演算子 (結果は) になり != true ます。If either operand is NaN, the result is false for all operators except !=, for which the result is true. 2つのオペランドの場合、は 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. たとえば、とのいずれかが NaN の場合、はですが x y x < y false!(x >= y) はです trueFor example, if either of x and y is NaN, then x < y is false, but !(x >= y) is true.

  • どちらのオペランドも NaN の場合、演算子は、2つの浮動小数点オペランドの値を順序付けと比較します。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
    

    とは、指定された浮動小数点 min max 形式で表現できる最小および最大の正の有限値です。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.
    • 正の無限大は、他のすべての値よりも大きいと見なされますが、もう1つの正の無限大と同じです。A positive infinity is considered greater than all other values, but equal to another positive infinity.

10進数の比較演算子Decimal comparison operators

定義済みの10進数比較演算子は次のとおりです。The predefined decimal comparison operators are:

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);

これらの各演算子は、2つの10進オペランドの数値を比較し、 bool 特定の関係がまたはであるかどうかを示す値を返し true false ます。Each of these operators compares the numeric values of the two decimal operands and returns a bool value that indicates whether the particular relation is true or false. 各10進数の比較は、型の対応する関係演算子または等値演算子を使用することと同じです System.DecimalEach decimal comparison is equivalent to using the corresponding relational or equality operator of type System.Decimal.

ブール等値演算子Boolean equality operators

定義済みのブール等価演算子は次のとおりです。The predefined boolean equality operators are:

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

との両方がであるか、 == true x y true またはとの両方 x y false がである場合、の結果はになります。The result of == is true if both x and y are true or if both x and y are false. それ以外の場合、結果は false です。Otherwise, the result is false.

との両方がであるか、 != false x y true またはとの両方 x y false がである場合、の結果はになります。The result of != is false if both x and y are true or if both x and y are false. それ以外の場合、結果は true です。Otherwise, the result is true. オペランドが型の場合 bool 、演算子は != 演算子と同じ結果を生成し ^ ます。When the operands are of type bool, the != operator produces the same result as the ^ operator.

列挙型比較演算子Enumeration comparison operators

すべての列挙型には、次の定義済みの比較演算子が暗黙的に用意されています。Every enumeration type implicitly provides the following predefined 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);

を評価した結果、 x op y xy は、基になる型を持つ列挙型の式で E あり、 U op 比較演算子の1つであり、評価とまったく同じです ((U)x) op ((U)y)The result of evaluating x op y, where x and y are expressions of an enumeration type E with an underlying type U, and op is one of the comparison operators, is exactly the same as evaluating ((U)x) op ((U)y). つまり、列挙型の比較演算子は、単に2つのオペランドの基になる整数値を比較します。In other words, the enumeration type comparison operators simply compare the underlying integral values of the two operands.

参照型等値演算子Reference type equality operators

定義済みの参照型等値演算子は次のとおりです。The predefined reference type equality operators are:

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

演算子は、2つの参照の等価性または非等価性を比較した結果を返します。The operators return the result of comparing the two references for equality or non-equality.

定義済みの参照型等値演算子は、型のオペランドを受け入れるため object 、適用可能なメンバーとメンバーを宣言しないすべての型に適用され operator == operator != ます。Since the predefined reference type equality operators accept operands of type object, they apply to all types that do not declare applicable operator == and operator != members. 反対に、適用可能なユーザー定義等値演算子は、定義済みの参照型等値演算子を効果的に非表示にします。Conversely, any applicable user-defined equality operators effectively hide the predefined reference type equality operators.

定義済みの参照型等値演算子には、次のいずれかが必要です。The predefined reference type equality operators require one of the following:

  • どちらのオペランドも、 reference_type またはリテラルであると認識される型の値です nullBoth 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.
  • 1つのオペランドは型の値です T 。ここで T 、は type_parameter で、もう一方のオペランドはリテラル null です。One 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.

これらの条件のいずれかが満たされていない限り、バインド時エラーが発生します。Unless one of these conditions are true, a binding-time error occurs. これらの規則の主な影響は次のとおりです。Notable implications of these rules are:

  • 定義済みの参照型等値演算子を使用して、バインド時に異なることがわかっている2つの参照を比較するためのバインド時エラーです。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. たとえば、オペランドのバインド時の型がとの2つのクラス型であり、また A B はのどちらか一方がではない場合、 A B 2 つのオペランドが同じオブジェクトを参照することはできません。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.

次の例では、制約のない型パラメーター型の引数がであるかどうかを確認 null します。The following example checks whether an argument of an unconstrained type parameter type is null.

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

x == nullが値型を表している場合でも、コンストラクトは許可され T false T ます。が値型の場合、結果は単純にとして定義されます。The x == null construct is permitted even though T could represent a value type, and the result is simply defined to be false when T is a value type.

フォーム x == y またはの操作 x != y (適用可能または存在する場合) については、 operator == 演算子のオーバーロードの operator != 解決 (二項演算子のオーバーロードの解決) 規則によって、定義済みの参照型等値演算子ではなく、その演算子が選択されます。For an operation of the form x == y or x != y, if any applicable operator == or operator != exists, the operator overload resolution (Binary operator overload resolution) rules will select that operator instead of the predefined reference type equality operator. ただし、オペランドの一方または両方を明示的に型にキャストすることで、定義済みの参照型等値演算子を常に選択でき object ます。However, it is always possible to select the predefined reference type equality operator by explicitly casting one or both of the operands to type object. 例を示します。The example

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);
    }
}

この例では、次のように出力されます。produces the output

True
False
False
False

s変数と t 変数は、同じ文字を含む2つの異なるインスタンスを参照し string ます。The s and t variables refer to two distinct string instances containing the same characters. True2 つのオペランドの型がの場合、定義済みの文字列等値演算子 (文字列等値演算子) が選択されているため、最初の比較結果が出力され 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.

上記の手法は、値型では意味がないことに注意してください。Note that the above technique is not meaningful for value types. 例を示します。The example

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

Falseキャストによって、ボックス化された値の2つのインスタンスへの参照が作成されるため、出力さ int れます。outputs False because the casts create references to two separate instances of boxed int values.

文字列等値演算子String equality operators

事前定義された文字列等値演算子は次のとおりです。The predefined string equality operators are:

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

string次のいずれかに該当する場合、2つの値は等しいと見なされます。Two string values are considered equal when one of the following is true:

  • 両方の値が null です。Both values are null.
  • 両方の値は、長さが同じ文字列インスタンスへの null 参照と、各文字位置に同一の文字を持ちます。Both values are non-null references to string instances that have identical lengths and identical characters in each character position.

文字列の等値演算子は、文字列参照ではなく文字列値を比較します。The string equality operators compare string values rather than string references. 2つの個別の文字列インスタンスにまったく同じ文字シーケンスが含まれている場合、文字列の値は同じですが、参照が異なります。When two separate string instances contain the exact same sequence of characters, the values of the strings are equal, but the references are different. 参照型等値演算子」で説明されているように、参照型等値演算子を使用すると、文字列値ではなく文字列参照を比較できます。As described in Reference type equality operators, the reference type equality operators can be used to compare string references instead of string values.

デリゲート等値演算子Delegate equality operators

すべてのデリゲート型には、次の定義済みの比較演算子が暗黙的に用意されています。Every delegate type implicitly provides the following predefined comparison operators:

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

次の2つのデリゲートインスタンスが等しいと見なされます。Two delegate instances are considered equal as follows:

  • デリゲートインスタンスのいずれかがの場合は 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.
  • 両方のデリゲートインスタンスが呼び出しリスト (デリゲート宣言) を持っている場合、それらのインスタンスは、呼び出しリストが同じ長さであり、1つの呼び出しリスト内の各エントリが、他の呼び出しリストにおいて、対応するエントリに順番に等しいと見なされます。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.

次の規則は、呼び出しリストエントリが等しいかどうかを制御します。The following rules govern the equality of invocation list entries:

  • 2つの呼び出しリストエントリが両方とも同じ静的メソッドを参照している場合、エントリは同じになります。If two invocation list entries both refer to the same static method then the entries are equal.
  • 2つの呼び出しリストエントリが、(参照等値演算子で定義されているように) 同じターゲットオブジェクトで同じ非静的メソッドを参照している場合、エントリは同じになります。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_expression s または lambda_expression の評価から生成された呼び出しリストのエントリは、同じにすることができます (ただし、必須ではありません)。Invocation list entries produced from evaluation of semantically identical anonymous_method_expression s or lambda_expression s with the same (possibly empty) set of captured outer variable instances are permitted (but not required) to be equal.

等値演算子と nullEquality operators and null

==演算子と != 演算子は、1つのオペランドが 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.

いずれかの形式の操作の場合For an operation of one of the forms

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

ここで、 x は null 許容型の式で、演算子のオーバーロードの解決 (二項演算子のオーバーロードの解決) が適用可能な演算子を見つけることができない場合、結果はのプロパティから計算され HasValue x ます。where x is an expression of a nullable type, if operator overload resolution (Binary operator overload resolution) fails to find an applicable operator, the result is instead computed from the HasValue property of x. 具体的には、最初の2つの形式はに変換され、 !x.HasValue 最後の2つの形式はに変換され x.HasValue ます。Specifically, the first two forms are translated into !x.HasValue, and last two forms are translated into x.HasValue.

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 T 参照変換、ボックス化変換、またはボックス化解除変換によって、が型に正常に変換されたかどうかを示すブール値です。The 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 許容型で、の値が null の場合、 E 結果は false になります。If E is a method group or the null literal, of if the type of E is a reference type or a nullable type and the value of E is null, the result is false.
  • それ以外の場合は、 D 次のようにの動的な型を表し E ます。Otherwise, let D represent the dynamic type of E as follows:
    • の型 E が参照型の場合、 D はによって参照されるインスタンスのランタイム型です EIf the type of E is a reference type, D is the run-time type of the instance reference by E.
    • の型が null 許容型である場合 ED はその null 許容型の基になる型です。If the type of E is a nullable type, D is the underlying type of that nullable type.
    • の型 E が null 非許容の値型である場合 D 、はの型 E です。If the type of E is a non-nullable value type, D is the type of E.
  • 操作の結果は、次のようにとによっ D T て異なります。The result of the operation depends on D and T as follows:
    • が参照型である場合、 T D とが T 同じ型である場合、が参照型であるか、からに暗黙的に参照変換が行われた場合、 D または D が値型であり、 T D からへのボックス変換で D T ある場合、結果は true になります。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 許容型である場合、 D がの基になる型である場合、結果は true になり T ます。If T is a nullable type, the result is true if D is the underlying type of T.
    • Tが null 非許容の値型である場合、との型が同じである場合、結果は true になり D T ます。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.

ユーザー定義の変換は、演算子では考慮されないことに注意 is してください。Note that user defined conversions, are not considered by the is operator.

as 演算子The as operator

演算子は、 as 特定の参照型または null 許容型に値を明示的に変換するために使用されます。The as operator is used to explicitly convert a value to a given reference type or nullable type. キャスト式 (cast 式) とは異なり、 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. さらに、次のうち少なくとも1つが true である必要があります。そうでない場合は、コンパイル時エラーが発生します。Furthermore, at least one of the following must be true, or otherwise a compile-time error occurs:

のコンパイル時の型 E がでない場合 dynamic 、操作は E as TIf the compile-time type of E is not dynamic, the operation E as T produces the same result as

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

ただし、E が評価されるのは 1 回だけです。except that E is only evaluated once. コンパイラは、上記の拡張に E as T よって暗黙的に指定された2つの動的な型チェックではなく、最大で1つの動的な型チェックを実行するように最適化する必要があります。The compiler can be expected to optimize E as T to perform at most one dynamic type check as opposed to the two dynamic type checks implied by the expansion above.

のコンパイル時の型がの場合、 E dynamic キャスト演算子とは異なり、 as 演算子は動的にバインドされません (動的バインド)。If the compile-time type of E is dynamic, unlike the cast operator the as operator is not dynamically bound (Dynamic binding). したがって、この場合の展開は次のようになります。Therefore the expansion in this case is:

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

ユーザー定義変換など、一部の変換は演算子では実行できず、 as キャスト式を使用して実行する必要があることに注意してください。Note that some conversions, such as user defined conversions, are not possible with the as operator and should instead be performed using cast expressions.

この例では、In the example

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

の型パラメーター T G は、クラスの制約があるため、参照型であることがわかっています。the type parameter T of G is known to be a reference type, because it has the class constraint. の型パラメーター U H がではありません。したがって、で演算子を使用すること as H はできません。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
    ;

論理演算子のオペランドにコンパイル時の型がある場合 dynamic 、式は動的にバインドされます (動的バインド)。If an operand of a logical operator has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). この場合、式のコンパイル時の型はであり、 dynamic 以下に示す解決方法は、コンパイル時の型を持つオペランドの実行時の型を使用して実行時に行われ dynamic ます。In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

フォームの操作 x op y op (は論理演算子の1つ) では、オーバーロードの解決 (二項演算子のオーバーロードの解決) が適用され、特定の演算子の実装を選択します。For an operation of the form x op y, where op is one of the logical operators, overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. オペランドは選択した演算子のパラメーターの型に変換され、結果の型は演算子の戻り値の型になります。The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.

定義済みの論理演算子については、次のセクションで説明します。The predefined logical operators are described in the following sections.

整数の論理演算子Integer logical operators

定義済みの整数の論理演算子は次のとおりです。The predefined integer logical operators are:

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);

演算子は、2つのオペランドのビットごとの論理を計算します。演算子は2つのオペランドのビットごとの論理を計算 & AND し、 | OR ^ 演算子は OR 2 つのオペランドのビットごとの論理排他的を計算します。The & 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 には、次の定義済みの論理演算子が暗黙的に用意されています。Every enumeration type E implicitly provides the following predefined logical operators:

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

を評価した結果 x op y x 。と y は、基になる型を持つ列挙型の式で E あり、 U op 論理演算子の1つであり、評価とまったく同じです (E)((U)x op (U)y)The result of evaluating x op y, where x and y are expressions of an enumeration type E with an underlying type U, and op is one of the logical operators, is exactly the same as evaluating (E)((U)x op (U)y). 言い換えると、列挙型の論理演算子は、2つのオペランドの基になる型に対して論理演算を実行するだけです。In other words, the enumeration type logical operators simply perform the logical operation on the underlying type of the two operands.

ブール論理演算子Boolean logical operators

定義済みのブール型の論理演算子は次のとおりです。The predefined boolean logical operators are:

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

xy の両方が true であれば、x & y の結果は true です。The result of x & y is true if both x and y are true. それ以外の場合、結果は false です。Otherwise, the result is false.

またはの x | y いずれかがの場合、の結果はになり true x y true ます。The result of x | y is true if either x or y is true. それ以外の場合、結果は false です。Otherwise, the result is false.

がで、がの場合、またはがで、がである場合、の結果 x ^ y はになり true x true y false x false y true ます。The result of x ^ y is true if x is true and y is false, or x is false and y is true. それ以外の場合、結果は false です。Otherwise, the result is false. オペランドが型の場合 bool 、演算子は ^ 演算子と同じ結果を計算し != ます。When the operands are of type bool, the ^ operator computes the same result as the != operator.

Null 許容のブール型論理演算子Nullable boolean logical operators

Null 許容のブール型は、、、 bool? およびの3つの値を表すことができ、 true 概念的には、 false null SQL のブール式に使用される3つの値の型に似ています。The nullable boolean type bool? can represent three values, true, false, and null, and is conceptually similar to the three-valued type used for boolean expressions in SQL. オペランドに対しておよび演算子によって生成される結果が & | bool? SQL の3つの値のロジックと一致するようにするために、次の定義済みの演算子が用意されています。To ensure that the results produced by the & and | operators for bool? operands are consistent with SQL's three-valued logic, the following predefined operators are provided:

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

次の表は、、、およびの値のすべての組み合わせに対して、これらの演算子によって生成される結果を示して true false null います。The following table lists the results produced by these operators for all combinations of the values true, false, and null.

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
    ;

&&And 演算子は、 || and 演算子の条件付きバージョンです & |The && and || operators are conditional versions of the & and | operators:

  • 操作は、 x && y x & y がで y ない場合にのみ評価される点を除いて、操作に対応し x false ます。The operation x && y corresponds to the operation x & y, except that y is evaluated only if x is not false.
  • 操作は、 x || y x | y がで y ない場合にのみ評価される点を除いて、操作に対応し x true ます。The operation x || y corresponds to the operation x | y, except that y is evaluated only if x is not true.

条件付き論理演算子のオペランドにコンパイル時の型がある場合 dynamic 、式は動的にバインドされます (動的バインド)。If an operand of a conditional logical operator has the compile-time type dynamic, then the expression is dynamically bound (Dynamic binding). この場合、式のコンパイル時の型はであり、 dynamic 以下に示す解決方法は、コンパイル時の型を持つオペランドの実行時の型を使用して実行時に行われ dynamic ます。In this case the compile-time type of the expression is dynamic, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic.

またはの形式の x && y 操作 x || 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,

  • オーバーロードの解決が1つの最適な演算子を見つけることができない場合、またはオーバーロードの解決で定義済みの整数の論理演算子が1つ選択された場合、バインド時エラーが発生します。If overload resolution fails to find a single best operator, or if overload resolution selects one of the predefined integer logical operators, a binding-time error occurs.
  • それ以外の場合、選択した演算子が、定義済みのブール型論理演算子 (ブール型論理演算子) または null 許容ブール値論理演算子 (null 許容のブール値論理演算子) のいずれかである場合、この操作は、「 ブール条件論理演算子」の説明に従って処理されます。Otherwise, if the selected operator is one of the predefined boolean logical operators (Boolean logical operators) or nullable boolean logical operators (Nullable boolean logical operators), the operation is processed as described in Boolean conditional logical operators.
  • それ以外の場合、選択された演算子はユーザー定義の演算子であり、操作は ユーザー定義の条件付き論理演算子の説明に従って処理されます。Otherwise, the selected operator is a user-defined operator, and the operation is processed as described in User-defined conditional logical operators.

条件付き論理演算子を直接オーバーロードすることはできません。It is not possible to directly overload the conditional logical operators. ただし、条件付き論理演算子は、通常の論理演算子の観点で評価されるため、通常の論理演算子のオーバーロードは、特定の制限がある、条件付き論理演算子のオーバーロードとも見なされます。However, because the conditional logical operators are evaluated in terms of the regular logical operators, overloads of the regular logical operators are, with certain restrictions, also considered overloads of the conditional logical operators. 詳細については 、ユーザー定義の条件付き論理演算子に関するページを参照してください。This is described further in User-defined conditional logical operators.

ブール条件論理演算子Boolean conditional logical operators

またはのオペランドが型である場合、または && || bool オペランドが、適用可能なまたはを定義していない型であり、 operator & への暗黙的な operator | 変換を定義する場合 bool 、操作は次のように処理されます。When the operands of && or || are of type bool, or when the operands are of types that do not define an applicable operator & or operator |, but do define implicit conversions to bool, the operation is processed as follows:

  • 操作 x && y はとして評価され x ? y : false ます。The operation x && y is evaluated as x ? y : false. つまり、 x は最初に評価され、型に変換され bool ます。In other words, x is first evaluated and converted to type bool. 次に、がの場合、 x true 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 : y ます。The operation x || y is evaluated as x ? true : y. つまり、 x は最初に評価され、型に変換され bool ます。In other words, x is first evaluated and converted to type bool. 次に、がの場合、 x true 操作の結果はに true なります。Then, if x is true, the result of the operation is true. それ以外の場合 y は、が評価され、型に変換され bool ます。これが演算の結果になります。Otherwise, y is evaluated and converted to type bool, and this becomes the result of the operation.

ユーザー定義の条件付き論理演算子User-defined conditional logical operators

またはのオペランド && || が、適切なユーザー定義のまたはを宣言する型である場合、 operator & operator | 次の両方が true である必要があり T ます。は、選択した演算子が宣言されている型です。When the operands of && or || are of types that declare an applicable user-defined operator & or operator |, both of the following must be true, where T is the type in which the selected operator is declared:

  • 戻り値の型と、選択した演算子の各パラメーターの型はである必要があり T ます。The return type and the type of each parameter of the selected operator must be T. 言い換えると、演算子は、 AND 型の2つのオペランドの論理 or 論理を計算する必要があり、 OR T 型の結果を返す必要があり 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 true operator false ます。T must contain declarations of operator true and operator false.

これらの要件のいずれかが満たされていない場合、バインド時エラーが発生します。A binding-time error occurs if either of these requirements is not satisfied. それ以外の場合、 && または操作は、 || ユーザー定義の operator true または選択され operator false たユーザー定義演算子と組み合わせて評価されます。Otherwise, the && or || operation is evaluated by combining the user-defined operator true or operator false with the selected user-defined operator:

  • 操作 x && y はとして評価され T.false(x) ? x : T.&(x, y) ます。ここで、は、で宣言されたの T.false(x) 呼び出しであり、は選択されたの operator false T 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 結果に対して呼び出されて、が確実に false であるかどうかを判断し x ます。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 operator & 値と、に対して計算された値に対して呼び出されて、 x 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) 呼び出しであり、は選択されたの operator true T 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 結果に対してが呼び出されて、が確実に true であるかどうかが判断され x ます。In other words, x is first evaluated and operator true is invoked on the result to determine if x is definitely true. 次に、 x が確実に true になると、演算の結果は、以前にに対して計算された値になり x ます。Then, if x is definitely true, the result of the operation is the value previously computed for x. それ以外の場合、が評価され、選択されたが、に対して以前に計算された y operator | 値と、に対して計算された値に対して呼び出されて、 x 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 は1回だけ評価され、によって指定された式は評価されず、まったく評価もされ y ません。In either of these operations, the expression given by x is only evaluated once, and the expression given by y is either not evaluated or evaluated exactly once.

とを実装する型の例に operator true つい operator false ては、「 データベースのブール型」を参照してください。For an example of a type that implements operator true and operator false, see Database boolean type.

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 合体式は、null a ?? b a 許容型または参照型である必要があります。A null coalescing expression of the form a ?? b requires a to be of a nullable type or reference type. aが null 以外の場合、の結果はになり a ?? b a ます。それ以外の場合、結果はになり b ます。If a is non-null, the result of a ?? b is a; otherwise, the result is b. 操作は、 b が null の場合にのみ評価 a されます。The operation evaluates b only if a is null.

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 またはです。ここで、は (型を持つ) の型、はの型であり、が A0 A B A a a B b b A0 A null 許容型である場合はの基になる型です A 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 ?? b は、は次のように処理されます。Specifically, 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が動的な式の場合、結果の型はに dynamic なります。If b is a dynamic expression, the result type is dynamic. 実行時に、 a が最初に評価されます。At 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 許容型で、からへの暗黙的な変換が存在する場合、 b A0 結果の型はに A0 なります。Otherwise, if A exists and is a nullable type and an implicit conversion exists from b to A0, the result type is A0. 実行時に、 a が最初に評価されます。At 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 存在し、からへの暗黙的な変換が存在する場合、 b A 結果の型はに A なります。Otherwise, if A exists and an implicit conversion exists from b to A, the result type is A. 実行時に、 a が最初に評価されます。At 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 からへの暗黙的な変換が存在する場合、 a B 結果の型はに B なります。Otherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. 実行時に、 a が最初に評価されます。At run-time, a is first evaluated. aが null でない場合は、 a が型にラップ解除され、が A0 null 値が許容される場合は型に変換され、 A これが結果に 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.
  • それ以外の場合、 a とに b は互換性がなく、コンパイル時エラーが発生します。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. 次に、がの場合、 b true 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. 条件式は、との両方を評価することはありません x yA conditional expression never evaluates both x and y.

条件演算子は、右から左の操作がグループ化されていることを意味します。The conditional operator is right-associative, meaning that operations are grouped from right to left. たとえば、という形式の式 a ? b : c ? d : e はとして評価され a ? b : (c ? d : e) ます。For example, an expression of the form a ? b : c ? d : e is evaluated as a ? b : (c ? d : e).

演算子の最初のオペランドは ?: 、暗黙的に変換できる式、 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.

演算子の2番目と3番目のオペランドは、 x y ?: 条件式の型を制御します。The second and third operands, x and y, of the ?: operator control the type of the conditional expression.

  • xに型があり Xy 型を持つ場合 Y は、If x has type X and y has type Y then
    • からへの暗黙の変換 (暗黙の変換) が存在する場合、からへの変換で X Y はなく、 Y X 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 はなく、 X Y 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.
  • とのいずれか1つだけ x y が型を持っていて、との両方がその型に暗黙的に変換可能な場合は、それ x y が条件式の型になります。If only one of x and y has a type, and both x and y, of are implicitly convertible to that type, then that is the type of the conditional expression.
  • それ以外の場合は、式の型を特定できないため、コンパイル時エラーが発生します。Otherwise, no expression type can be determined, and a compile-time error occurs.

フォームの条件式の実行時処理は、次の手順で構成されてい b ? x : y ます。The run-time processing of a conditional expression of the form b ? x : y consists of the following steps:

  • まず、 b が評価され、 bool の値 b が決定されます。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.
    • それ以外の場合、の型によって定義されたは、 operator true b 値を生成するために呼び出され bool ます。Otherwise, the operator true defined by the type of b is invoked to produce a bool value.
  • bool上記の手順で生成された値がの場合は truex が評価され、条件式の型に変換されます。これが条件式の結果になります。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

匿名関数 は、"インライン" メソッド定義を表す式です。An anonymous function is an expression that represents an "in-line" method definition. 匿名関数は、それ自体の値または型を持っていませんが、互換性のあるデリゲートまたは式ツリー型に変換できます。An anonymous function does not have a value or type in and of itself, but is convertible to a compatible delegate or expression tree type. 匿名関数の変換の評価は、変換の対象の型によって異なります。これがデリゲート型である場合、変換は、匿名関数が定義するメソッドを参照するデリゲート値に評価されます。The evaluation of an anonymous function conversion depends on the target type of the conversion: If it is a delegate type, the conversion evaluates to a delegate value referencing the method which the anonymous function defines. 式ツリー型の場合、変換は、オブジェクト構造としてのメソッドの構造を表す式ツリーに評価されます。If it is an expression tree type, the conversion evaluates to an expression tree which represents the structure of the method as an object structure.

歴史的な理由により、匿名関数には2つの構文があります。つまり lambda_expression s と anonymous_method_expression s です。For historical reasons there are two syntactic flavors of anonymous functions, namely lambda_expression s and anonymous_method_expression s. ほとんどの場合、 lambda_expressionanonymous_method_expression より簡潔で表現力が豊かで、下位互換性のために言語に残されています。For almost all purposes, lambda_expression s are more concise and expressive than anonymous_method_expression s, which remain in the language for backwards compatibility.

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.

修飾子を持つ匿名関数 async は非同期関数で、「 async 関数」で説明されている規則に従います。An anonymous function with the async modifier is an async function and follows the rules described in Async functions.

Lambda_expression 形式の匿名関数のパラメーターは、明示的または暗黙的に型指定できます。The parameters of an anonymous function in the form of a lambda_expression can be explicitly or implicitly typed. 明示的に型指定されたパラメーターリストでは、各パラメーターの型が明示的に指定されます。In an explicitly typed parameter list, the type of each parameter is explicitly stated. 暗黙的に型指定されたパラメーターリストでは、匿名関数が発生したコンテキストからパラメーターの型が推論されます。具体的には、匿名関数が互換性のあるデリゲート型または式ツリー型に変換されると、その型はパラメーターの型 (匿名関数の変換) を提供します。In an implicitly typed parameter list, the types of the parameters are inferred from the context in which the anonymous function occurs—specifically, when the anonymous function is converted to a compatible delegate type or expression tree type, that type provides the parameter types (Anonymous function conversions).

暗黙的に型指定された単一のパラメーターを持つ匿名関数では、パラメーターリストからかっこを省略できます。In an anonymous function with a single, implicitly typed parameter, the parentheses may be omitted from the parameter list. つまり、という形式の匿名関数In other words, an anonymous function of the form

( param ) => expr

をに短縮できます。can be abbreviated to

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.

匿名関数の ブロック 本体に到達可能 (エンドポイントと到達可能性) は、匿名関数が到達できないステートメントの内部にある場合を除きます。A block body of an anonymous function is reachable (End points and reachability) unless the anonymous function occurs inside an unreachable statement.

次に、匿名関数の例をいくつか示します。Some examples of anonymous functions follow below:

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_expression s と anonymous_method_expression s の動作は、次の点を除いて同じです。The behavior of lambda_expression s and anonymous_method_expression s is the same except for the following points:

  • anonymous_method_expression s を使用すると、パラメーターリストを完全に省略でき、値パラメーターのリストのデリゲート型に convertibility が生成されます。anonymous_method_expression s permit the parameter list to be omitted entirely, yielding convertibility to delegate types of any list of value parameters.
  • lambda_expression s では、パラメーターの型を省略し、推論することができますが、 anonymous_method_expression s ではパラメーターの型を明示的に指定する必要があります。lambda_expression s permit parameter types to be omitted and inferred whereas anonymous_method_expression s require parameter types to be explicitly stated.
  • Lambda_expression の本体は、式またはステートメントブロックにすることができます。一方、 anonymous_method_expression の本体は、ステートメントブロックである必要があります。The body of a lambda_expression can be an expression or a statement block whereas the body of an anonymous_method_expression must be a statement block.
  • 互換性のある式ツリー型 (式ツリー型) に変換できるのは lambda_expression s だけです。Only lambda_expression s have conversions to compatible expression tree types (Expression tree types).

匿名関数のシグネチャAnonymous function signatures

匿名関数の省略可能な anonymous_function_signature は、匿名関数の名前と、必要に応じて、仮パラメーターの型を定義します。The optional anonymous_function_signature of an anonymous function defines the names and optionally the types of the formal parameters for the anonymous function. 匿名関数のパラメーターのスコープは、 anonymous_function_body です。The scope of the parameters of the anonymous function is the anonymous_function_body. (スコープ)パラメーターリストと共に (指定されている場合)、匿名メソッド本体は宣言空間 (宣言) を構成します。(Scopes) Together with the parameter list (if given) the anonymous-method-body constitutes a declaration space (Declarations). したがって、匿名関数のパラメーター名がローカル変数の名前、ローカル定数、またはスコープに anonymous_method_expression または lambda_expression が含まれている場合、コンパイル時にエラーが発生します。It is thus a compile-time error for the name of a parameter of the anonymous function to match the name of a local variable, local constant or parameter whose scope includes the anonymous_method_expression or lambda_expression.

匿名関数に explicit_anonymous_function_signature がある場合、互換性のあるデリゲート型と式ツリー型のセットは、同じ順序で同じパラメーターの型と修飾子を持つものに制限されます。If an anonymous function has an explicit_anonymous_function_signature, then the set of compatible delegate types and expression tree types is restricted to those that have the same parameter types and modifiers in the same order. メソッドグループの変換 (メソッドグループの変換) とは対照的に、匿名関数のパラメーター型の反変性はサポートされていません。In contrast to method group conversions (Method group conversions), contra-variance of anonymous function parameter types is not supported. 匿名関数に anonymous_function_signature がない場合、互換性のあるデリゲート型と式ツリー型のセットは、パラメーターを持たない型に制限され out ます。If an anonymous function does not have an anonymous_function_signature, then the set of compatible delegate types and expression tree types is restricted to those that have no out parameters.

Anonymous_function_signature には、属性またはパラメーター配列を含めることはできません。Note that an anonymous_function_signature cannot include attributes or a parameter array. ただし、パラメーターリストにパラメーター配列が含まれているデリゲート型との互換性がある anonymous_function_signatureNevertheless, an anonymous_function_signature may be compatible with a delegate type whose parameter list contains a parameter array.

互換性がある場合でも、式ツリー型への変換は、コンパイル時 (式ツリー型) で失敗する可能性があることにも注意してください。Note also that conversion to an expression tree type, even if compatible, may still fail at compile-time (Expression tree types).

匿名関数本体Anonymous function bodies

匿名関数の本体 ( または ブロック) には、次の規則が適用されます。The body (expression or block) of an anonymous function is subject to the following rules:

  • 匿名関数に署名が含まれている場合は、署名に指定されているパラメーターを本文で使用できます。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.
  • refまたはの out シグネチャに指定されたパラメーター (存在する場合) は、最も近い外側の匿名関数の場合を除き、本文がまたはパラメーターにアクセスするときのコンパイル時エラーになり ref out ます。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_expression または anonymous_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_expression または anonymous_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).

Lambda_expression または anonymous_method_expression の評価と呼び出し以外で匿名関数のブロックを実行する方法があるかどうかは、明示的に指定されていません。It is explicitly unspecified whether there is any way to execute the block of an anonymous function other than through evaluation and invocation of the lambda_expression or anonymous_method_expression. 特に、コンパイラは、1つまたは複数の名前付きメソッドまたは型をからことによって、匿名関数を実装することができます。In particular, the compiler may choose to implement an anonymous function by synthesizing one or more named methods or types. このような合成された要素の名前は、コンパイラ用に予約された形式である必要があります。The names of any such synthesized elements must be of a form reserved for compiler use.

オーバーロードの解決と匿名関数Overload resolution and anonymous functions

引数リスト内の匿名関数は、型の推定とオーバーロードの解決に関与します。Anonymous functions in an argument list participate in type inference and overload resolution. 厳密なルールについては、 「型の推定オーバーロードの解決 」を参照してください。Please refer to Type inference and Overload resolution for the exact rules.

次の例は、オーバーロードの解決での匿名関数の効果を示しています。The following example illustrates the effect of anonymous functions on overload resolution.

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>クラスには、2つのメソッドがあり 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. 抽出された値には、またはのいずれかを指定でき int double ます。結果の合計は、またはのいずれかになり int double ます。The extracted value can be either an int or a double and the resulting sum is likewise either an int or a double.

これら Sum のメソッドを使用して、詳細行のリストから注文の合計を計算することができます。The Sum methods could for example be used to compute sums from a list of detail lines in an order.

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

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

の最初の呼び出しでは、 orderDetails.Sum Sum 匿名関数 d => d. UnitCount はとの両方と互換性があるため、両方のメソッドが適用され Func<Detail,int> Func<Detail,double> ます。In the first invocation of orderDetails.Sum, both Sum methods are applicable because the anonymous function d => d. UnitCount is compatible with both Func<Detail,int> and Func<Detail,double>. ただし、への変換は Sum に変換するよりも優れているため、オーバーロードの解決では最初のメソッドが選択 Func<Detail,int> され Func<Detail,double> ます。However, overload resolution picks the first Sum method because the conversion to Func<Detail,int> is better than the conversion to Func<Detail,double>.

の2番目の呼び出しで orderDetails.Sum は、 Sum 匿名関数が d => d.UnitPrice * d.UnitCount 型の値を生成するため、2番目のメソッドのみが適用され double ます。In the second invocation of orderDetails.Sum, only the second Sum method is applicable because the anonymous function d => d.UnitPrice * d.UnitCount produces a value of type double. したがって、オーバーロードの解決では、その呼び出しの2番目のメソッドが選択さ Sum れます。Thus, overload resolution picks the second Sum method for that invocation.

匿名関数と動的バインドAnonymous functions and dynamic binding

匿名関数は、動的にバインドされた操作のレシーバー、引数、またはオペランドにすることはできません。An anonymous function cannot be a receiver, argument or operand of a dynamically bound operation.

外部変数Outer variables

スコープに lambda_expression または anonymous_method_expression が含まれているすべてのローカル変数、値パラメーター、またはパラメーター配列は、匿名関数の 外部変数 と呼ばれます。Any local variable, value parameter, or parameter array whose scope includes the lambda_expression or anonymous_method_expression is called an outer variable of the anonymous function. クラスのインスタンス関数メンバーでは、 this 値は値パラメーターと見なされ、関数メンバー内に含まれるすべての匿名関数の外部変数になります。In an instance function member of a class, the this value is considered a value parameter and is an outer variable of any anonymous function contained within the function member.

キャプチャされた外部変数Captured outer variables

外部変数が匿名関数によって参照されている場合、外部変数は匿名関数によって キャプチャ されたと言います。When an outer variable is referenced by an anonymous function, the outer variable is said to have been captured by the anonymous function. 通常、ローカル変数の有効期間は、関連付けられているブロックまたはステートメント (ローカル変数) の実行に制限されます。Ordinarily, the lifetime of a local variable is limited to execution of the block or statement with which it is associated (Local variables). ただし、取得した外部変数の有効期間は、匿名関数から作成されたデリゲートまたは式ツリーがガベージコレクションの対象になるまで、少なくとも拡張されます。However, the lifetime of a captured outer variable is extended at least until the delegate or expression tree created from the anonymous function becomes eligible for garbage collection.

この例では、In the example

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());
    }
}

ローカル変数 x は匿名関数によってキャプチャされ x ます。また、から返されたデリゲートがガベージコレクションの対象になるまで、の有効期間が少なくとも拡張され F ます (これはプログラムの最後まで発生しません)。the local variable x is captured by the anonymous function, and the lifetime of x is extended at least until the delegate returned from F becomes eligible for garbage collection (which doesn't happen until the very end of the program). 匿名関数の各呼び出しは、の同じインスタンスで動作するため、この x 例の出力は次のようになります。Since each invocation of the anonymous function operates on the same instance of x, the output of the example is:

1
2
3

ローカル変数または値パラメーターが匿名関数によってキャプチャされると、ローカル変数またはパラメーターは固定変数 (固定変数および移動可能変数) とは見なされなくなりますが、代わりに移動可能な変数と見なされます。When a local variable or a value parameter is captured by an anonymous function, the local variable or parameter is no longer considered to be a fixed variable (Fixed and moveable variables), but is instead considered to be a moveable variable. したがって、キャプチャされ unsafe た外部変数のアドレスを受け取るすべてのコードでは、最初にステートメントを使用して変数を修正する必要があり fixed ます。Thus any unsafe code that takes the address of a captured outer variable must first use the fixed statement to fix the variable.

Uncaptured 変数とは異なり、キャプチャされたローカル変数は複数の実行スレッドに同時に公開できます。Note that unlike an uncaptured variable, a captured local variable can be simultaneously exposed to multiple threads of execution.

ローカル変数のインスタンス化Instantiation of local variables

ローカル変数は、実行時に変数のスコープに入ると、 インスタンス化 されると見なされます。A local variable is considered to be instantiated when execution enters the scope of the variable. たとえば、次のメソッドが呼び出されると、ローカル変数 x がインスタンス化され、ループの反復ごとに3回初期化されます。For example, when the following method is invoked, the local variable x is instantiated and initialized three times—once for each iteration of the loop.

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

ただし、ループの外側の宣言を移動すると、 x 次の1つのインスタンスが生成され x ます。However, moving the declaration of x outside the loop results in a single instantiation of x:

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

キャプチャされていない場合、ローカル変数がインスタンス化される頻度を正確に観察する方法はありません。インスタンス化の有効期間が不整合になるため、各インスタンス化で同じストレージの場所を使用することができます。When not captured, there is no way to observe exactly how often a local variable is instantiated—because the lifetimes of the instantiations are disjoint, it is possible for each instantiation to simply use the same storage location. ただし、匿名関数がローカル変数をキャプチャすると、インスタンス化の効果が明らかになります。However, when an anonymous function captures a local variable, the effects of instantiation become apparent.

例を示します。The example

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();
    }
}

この例では、次のように出力されます。produces the output:

1
3
5

ただし、の宣言 x がループの外側に移動される場合は、次のようになります。However, when the declaration of x is moved outside the loop:

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;
}

出力は次のとおりです。the output is:

5
5
5

For ループが反復変数を宣言している場合、その変数自体がループの外側で宣言されていると見なされます。If a for-loop declares an iteration variable, that variable itself is considered to be declared outside of the loop. したがって、反復変数自体をキャプチャするように例が変更された場合は、次のようになります。Thus, if the example is changed to capture the iteration variable itself:

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

次のように出力を生成する反復変数のインスタンスは1つだけキャプチャされます。only one instance of the iteration variable is captured, which produces the output:

3
3
3

匿名関数デリゲートは、キャプチャされたいくつかの変数を共有し、他の変数のインスタンスを個別に持つことができます。It is possible for anonymous function delegates to share some captured variables yet have separate instances of others. たとえば、がに変更された場合は、次の F ようになります。For example, if F is changed to

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;
}

3つのデリゲートは、の同じインスタンス x をキャプチャしますが、のインスタンスは分離し、 y 出力は次のようになります。the three delegates capture the same instance of x but separate instances of y, and the output is:

1 1
2 1
3 1

個別の匿名関数は、外部変数の同じインスタンスをキャプチャできます。Separate anonymous functions can capture the same instance of an outer variable. この例では次のとおりです。In the example:

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());
    }
}

この2つの匿名関数は、ローカル変数の同じインスタンスをキャプチャ x し、その変数を使用して "通信" できます。the two anonymous functions capture the same instance of the local variable x, and they can thus "communicate" through that variable. この例の出力は次のとおりです。The output of the example is:

5
10

匿名関数式の評価Evaluation of anonymous function expressions

匿名関数は F 、常にデリゲート型または式ツリー型に変換する必要があり D E ます。直接またはデリゲート作成式の実行を使用し new D(F) ます。An anonymous function F must always be converted to a delegate type D or an expression tree type E, either directly or through the execution of a delegate creation expression new D(F). この変換は、「 匿名関数の変換」で説明されているように、匿名関数の結果を決定します。This conversion determines the result of the anonymous function, as described in Anonymous function conversions.

クエリ式Query expressions

クエリ式 には、SQL や XQuery などのリレーショナルクエリ言語と階層クエリ言語に似たクエリの言語統合構文が用意されています。Query expressions provide a language integrated syntax for queries that is similar to relational and hierarchical query languages such as SQL and XQuery.

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
    ;

クエリ式は句で始まり from 、または句のいずれかで終わり select group ます。A query expression begins with a from clause and ends with either a select or group clause. 最初の from 句の後には、0個以上 from の、、 let wherejoin または句を指定でき orderby ます。The initial from clause can be followed by zero or more from, let, where, join or orderby clauses. from 句は、_ シーケンス * の要素を範囲とする *範囲変数 _ を導入するジェネレーターです。Each from clause is a generator introducing a range variable _ which ranges over the elements of a _sequence**. let 句では、前の範囲変数によって計算された値を表す範囲変数を導入します。Each let clause introduces a range variable representing a value computed by means of previous range variables. where 句は、結果から項目を除外するフィルターです。Each where clause is a filter that excludes items from the result. join 句は、ソースシーケンスの指定されたキーを別のシーケンスのキーと比較し、一致するペアを生成します。Each join clause compares specified keys of the source sequence with keys of another sequence, yielding matching pairs. orderby 句は、指定された条件に従って項目を並べ替えます。最後の select or group 句は、範囲変数の観点から結果の形状を指定します。Each orderby clause reorders items according to specified criteria.The final select or group clause specifies the shape of the result in terms of the range variables. 最後に、 into 1 つのクエリの結果を後続のクエリでジェネレーターとして扱うことによって、句を使用してクエリを "スプライス" できます。Finally, an into clause can be used to "splice" queries by treating the results of one query as a generator in a subsequent query.

クエリ式のあいまいさAmbiguities in query expressions

クエリ式には、さまざまな "コンテキストキーワード" が含まれています。つまり、特定のコンテキストで特別な意味を持つ識別子です。Query expressions contain a number of "contextual keywords", i.e., identifiers that have special meaning in a given context. 具体的には、、、、、、、、、、、、 from where join on equals into let orderby ascending descending select group および by です。Specifically these are from, where, join, on, equals, into, let, orderby, ascending, descending, select, group and by. これらの識別子をキーワードまたは単純名として使用することによるクエリ式のあいまいさを回避するために、これらの識別子は、クエリ式内の任意の場所で出現するときにキーワードと見なされます。In order to avoid ambiguities in query expressions caused by mixed use of these identifiers as keywords or simple names, these identifiers are considered keywords when occurring anywhere within a query expression.

このため、クエリ式は、"" の後に "" from identifier ; 、" = "、または "" 以外の任意のトークンが続く "" で始まる任意の式です ,For this purpose, a query expression is any expression that starts with "from identifier" followed by any token except ";", "=" or ",".

これらの単語をクエリ式内で識別子として使用するには、プレフィックスとして " @ " (識別子) を付けることができます。In order to use these words as identifiers within a query expression, they can be prefixed with "@" (Identifiers).

クエリ式の変換Query expression translation

C# 言語では、クエリ式の実行セマンティクスが指定されていません。The C# language does not specify the execution semantics of query expressions. 代わりに、クエリ式は、クエリ 式パターン (クエリ式パターン) に準拠するメソッドの呼び出しに変換されます。Rather, query expressions are translated into invocations of methods that adhere to the query expression pattern (The query expression pattern). 具体的には、クエリ式は、、、、、、、、、、、およびという名前のメソッドの呼び出しに変換され Where Select SelectMany Join GroupJoin OrderBy OrderByDescending ThenBy ThenByDescending GroupBy Cast ます。これらのメソッドには、 クエリ式パターンで説明されているように、特定のシグネチャと結果型が必要です。Specifically, query expressions are translated into invocations of methods named Where, Select, SelectMany, Join, GroupJoin, OrderBy, OrderByDescending, ThenBy, ThenByDescending, GroupBy, and Cast.These methods are expected to have particular signatures and result types, as described in The query expression pattern. これらのメソッドは、クエリを実行するオブジェクトのインスタンスメソッド、またはオブジェクトの外部にある拡張メソッドにすることができ、クエリの実際の実行を実装します。These methods can be instance methods of the object being queried or extension methods that are external to the object, and they implement the actual execution of the query.

クエリ式からメソッド呼び出しへの変換は、型のバインディングまたはオーバーロードの解決が行われる前に行われる構文のマッピングです。The translation from query expressions to method invocations is a syntactic mapping that occurs before any type binding or overload resolution has been performed. 変換は構文的に正しいことが保証されていますが、意味のある C# コードを生成することは保証されていません。The translation is guaranteed to be syntactically correct, but it is not guaranteed to produce semantically correct C# code. クエリ式の変換後、結果のメソッド呼び出しは通常のメソッド呼び出しとして処理され、メソッドが存在しない場合、引数の型が正しくない場合、またはメソッドがジェネリックで、型の推定が失敗した場合などに、エラーが明らかになります。Following translation of query expressions, the resulting method invocations are processed as regular method invocations, and this may in turn uncover errors, for example if the methods do not exist, if arguments have wrong types, or if the methods are generic and type inference fails.

クエリ式は、さらに縮小することができなくなるまで、次の変換を繰り返し適用することで処理されます。A query expression is processed by repeatedly applying the following translations until no further reductions are possible. 翻訳はアプリケーション順に一覧表示されます。各セクションでは、前のセクションで説明した翻訳が徹底的に実行されたことを前提としています。また、1つのセクションは、後で同じクエリ式の処理中に再検討されることはありません。The translations are listed in order of application: each section assumes that the translations in the preceding sections have been performed exhaustively, and once exhausted, a section will not later be revisited in the processing of the same query expression.

範囲変数への代入は、クエリ式では許可されていません。Assignment to range variables is not allowed in query expressions. ただし、C# の実装では、この制限が常に適用されるとは限りません。これは、ここで説明する構文変換スキームではできない場合があるためです。However a C# implementation is permitted to not always enforce this restriction, since this may sometimes not be possible with the syntactic translation scheme presented here.

特定の翻訳では、によって示される透過的な識別子を使用して範囲変数を挿入 * します。Certain translations inject range variables with transparent identifiers denoted by *. 透過的な識別子の特別なプロパティについては、「 透過的識別子」で詳しく説明します。The special properties of transparent identifiers are discussed further in Transparent identifiers.

継続を含む Select および groupby 句Select and groupby clauses with continuations

継続を含むクエリ式A query expression with a continuation

from ... into x ...

はに変換されます。is translated into

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

以降のセクションの変換では、クエリに継続がないことを前提としてい into ます。The translations in the following sections assume that queries have no into continuations.

例を示します。The example

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

はに変換されます。is translated into

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

最終的な変換は、the final translation of which is

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

明示的な範囲変数の型Explicit range variable types

from範囲変数の型を明示的に指定する句A from clause that explicitly specifies a range variable type

from T x in e

はに変換されます。is translated into

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

join範囲変数の型を明示的に指定する句A join clause that explicitly specifies a range variable type

join T x in e on k1 equals k2

はに変換されます。is translated into

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

以降のセクションの変換では、クエリに明示的な範囲変数の型がないと想定しています。The translations in the following sections assume that queries have no explicit range variable types.

例を示します。The example

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

はに変換されます。is translated into

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

最終的な変換は、the final translation of which is

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

明示的な範囲変数型は、非ジェネリックインターフェイスを実装するコレクションに対してクエリを実行する場合に便利です IEnumerable が、ジェネリックインターフェイスは使用できません IEnumerable<T>Explicit range variable types are useful for querying collections that implement the non-generic IEnumerable interface, but not the generic IEnumerable<T> interface. 上記の例では、が型である場合、これが当てはまり customers ArrayList ます。In the example above, this would be the case if customers were of type ArrayList.

逆クエリ式Degenerate query expressions

フォームのクエリ式A query expression of the form

from x in e select x

はに変換されます。is translated into

( e ) . Select ( x => x )

例を示します。The example

from c in customers
select c

はに変換されます。is translated into

customers.Select(c => c)

逆クエリ式とは、ソースの要素を普通に選択したものです。A degenerate query expression is one that trivially selects the elements of the source. 変換の後の段階では、他の変換ステップによって導入された逆のクエリをソースに置き換えることによって削除します。A later phase of the translation removes degenerate queries introduced by other translation steps by replacing them with their source. ただし、クエリ式の結果がソースオブジェクト自体にならないようにすることが重要です。これにより、クエリのクライアントに対するソースの型と id が明らかになります。It is important however to ensure that the result of a query expression is never the source object itself, as that would reveal the type and identity of the source to the client of the query. したがって、この手順では、ソースで明示的にを呼び出すことによって、ソースコードに直接書き込まれた低次元クエリを保護し Select ます。Therefore this step protects degenerate queries written directly in source code by explicitly calling Select on the source. その後、 Select これらのメソッドがソースオブジェクト自体を返さないようにするために、およびその他のクエリ演算子を実装する必要があります。It is then up to the implementers of Select and other query operators to ensure that these methods never return the source object itself.

From、let、where、join、orderby 句From, let, where, join and orderby clauses

2番目の句の from 後に句を指定したクエリ式 selectA query expression with a second from clause followed by a select clause

from x1 in e1
from x2 in e2
select v

はに変換されます。is translated into

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

2番目 from の句の後に句以外のものが続くクエリ式 selectA query expression with a second from clause followed by something other than a select clause:

from x1 in e1
from x2 in e2
...

はに変換されます。is translated into

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

句を含むクエリ式 letA query expression with a let clause

from x in e
let y = f
...

はに変換されます。is translated into

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

句を含むクエリ式 whereA query expression with a where clause

from x in e
where f
...

はに変換されます。is translated into

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

句の後に句が含まれて join いないクエリ式 into selectA query expression with a join clause without an into followed by a select clause

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

はに変換されます。is translated into

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

句の join into 後に句以外の何かが指定されていない句を含むクエリ式 selectA query expression with a join clause without an into followed by something other than a select clause

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

はに変換されます。is translated into

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

join句の into 後に select 句を指定したクエリ式A query expression with a join clause with an into followed by a select clause

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

はに変換されます。is translated into

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

句の join into 後に句以外の値が指定されているクエリ式 selectA query expression with a join clause with an into followed by something other than a select clause

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

はに変換されます。is translated into

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

句を含むクエリ式 orderbyA query expression with an orderby clause

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

はに変換されます。is translated into

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

順序句で方向インジケーターが指定されている場合 descending OrderByDescending は、代わりにまたはの呼び出し ThenByDescending が生成されます。If an ordering clause specifies a descending direction indicator, an invocation of OrderByDescending or ThenByDescending is produced instead.

次の変換では let 、、 wherejoin または句がなく、 orderby 各クエリ式に1つ以上の初期 from 句がないことを想定しています。The following translations assume that there are no let, where, join or orderby clauses, and no more than the one initial from clause in each query expression.

例を示します。The example

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

はに変換されます。is translated into

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

例を示します。The example

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

はに変換されます。is translated into

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

最終的な変換は、the final translation of which is

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 })

ここで x 、はコンパイラによって生成される識別子であり、それ以外は非表示でアクセスできません。where x is a compiler generated identifier that is otherwise invisible and inaccessible.

例を示します。The example

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

はに変換されます。is translated into

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 }

最終的な変換は、the final translation of which is

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 })

ここで x 、はコンパイラによって生成される識別子であり、それ以外は非表示でアクセスできません。where x is a compiler generated identifier that is otherwise invisible and inaccessible.

例を示します。The example

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

はに変換されます。is translated into

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

例を示します。The example

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 }

はに変換されます。is translated into

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 }

最終的な変換は、the final translation of which is

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)

xy は、非表示でアクセスできない、コンパイラによって生成される識別子です。where x and y are compiler generated identifiers that are otherwise invisible and inaccessible.

例を示します。The example

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

最終翻訳has the final translation

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

Select 句Select clauses

フォームのクエリ式A query expression of the form

from x in e select v

はに変換されます。is translated into

( e ) . Select ( x => v )

v が識別子 x の場合を除き、変換は単純です。except when v is the identifier x, the translation is simply

( e )

次に例を示します。For example

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

は単にに変換されます。is simply translated into

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

Groupby 句Groupby clauses

フォームのクエリ式A query expression of the form

from x in e group v by k

はに変換されます。is translated into

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

v が識別子 x である場合を除き、変換はexcept when v is the identifier x, the translation is

( e ) . GroupBy ( x => k )

例を示します。The example

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

はに変換されます。is translated into

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

透過的な識別子Transparent identifiers

特定の翻訳では、*透過識別子 _ を使用して範囲変数を挿入 _ します。Certain translations inject range variables with *transparent identifiers _ denoted by _. 透過的な識別子は、適切な言語機能ではありません。これらは、クエリ式の変換プロセスの中間手順としてのみ存在します。Transparent identifiers are not a proper language feature; they exist only as an intermediate step in the query expression translation process.

クエリ変換によって透過的識別子が挿入されると、その後の変換ステップによって透過的識別子が匿名関数および匿名オブジェクト初期化子に反映されます。When a query translation injects a transparent identifier, further translation steps propagate the transparent identifier into anonymous functions and anonymous object initializers. これらのコンテキストでは、透過的な識別子の動作は次のようになります。In those contexts, transparent identifiers have the following behavior:

  • 匿名関数のパラメーターとして透過的識別子が発生した場合、関連付けられた匿名型のメンバーは、匿名関数の本体のスコープ内に自動的に含まれます。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.
  • 前述の変換手順では、透過的識別子は常に匿名型と共に導入され、複数の範囲変数を1つのオブジェクトのメンバーとしてキャプチャすることを目的としています。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.

例を示します。The example

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

はに変換されます。is translated into

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

これは、さらにに変換されます。which is further translated into

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

これは、透過的な識別子が消去されると、which, when transparent identifiers are erased, is equivalent to

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

ここで x 、はコンパイラによって生成される識別子であり、それ以外は非表示でアクセスできません。where x is a compiler generated identifier that is otherwise invisible and inaccessible.

例を示します。The example

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 }

はに変換されます。is translated into

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 }

これは、which is further reduced to

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 })

最終的な変換は、the final translation of which is

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 })

ここ x で、、、 y z は、非表示でアクセスできない、コンパイラによって生成される識別子です。where x, y, and z are compiler generated identifiers that are otherwise invisible and inaccessible.

クエリ式パターンThe query expression pattern

クエリ式パターン は、型がクエリ式をサポートするために実装できるメソッドのパターンを確立します。The Query expression pattern establishes a pattern of methods that types can implement to support query expressions. クエリ式は構文マッピングによってメソッドの呼び出しに変換されるため、型はクエリ式パターンを実装する方法において非常に柔軟です。Because query expressions are translated to method invocations by means of a syntactic mapping, types have considerable flexibility in how they implement the query expression pattern. たとえば、パターンのメソッドは、インスタンスメソッドとして実装することも、拡張メソッドとして実装することもできます。これは、2つの呼び出し構文が同じであるためです。また、匿名関数は両方に変換可能であるため、メソッドはデリゲートまたは式ツリーを要求できます。For example, the methods of the pattern can be implemented as instance methods or as extension methods because the two have the same invocation syntax, and the methods can request delegates or expression trees because anonymous functions are convertible to both.

C<T>次に、クエリ式パターンをサポートするジェネリック型の推奨される図形を示します。The recommended shape of a generic type C<T> that supports the query expression pattern is shown below. ジェネリック型は、パラメーターと結果の型の間の適切なリレーションシップを示すために使用されますが、非ジェネリック型のパターンを実装することもできます。A generic type is used in order to illustrate the proper relationships between parameter and result types, but it is possible to implement the pattern for non-generic types as well.

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; }
}

上記のメソッドでは、汎用デリゲート型 Func<T1,R> とを使用し Func<T1,T2,R> ますが、パラメーターと結果の型で同じリレーションシップを持つ他のデリゲート型または式ツリー型を使用することもできます。The methods above use the generic delegate types Func<T1,R> and Func<T1,T2,R>, but they could equally well have used other delegate or expression tree types with the same relationships in parameter and result types.

との間に推奨されるリレーションシップがあることを確認し C<T> O<T> ます。これにより、 ThenBy ThenByDescending メソッドとメソッドは、またはの結果でのみ使用できるようになり OrderBy OrderByDescending ます。Notice the recommended relationship between C<T> and O<T> which ensures that the ThenBy and ThenByDescending methods are available only on the result of an OrderBy or OrderByDescending. また、の結果の推奨される構造 (シーケンスのシーケンス) にも注目して GroupBy ください。各内部シーケンスには追加のプロパティがあり Key ます。Also notice the recommended shape of the result of GroupBy -- a sequence of sequences, where each inner sequence has an additional Key property.

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

代入演算子は、変数、プロパティ、イベント、またはインデクサー要素に新しい値を代入します。The assignment operators assign a new value to a variable, a property, an event, or an indexer element.

assignment
    : unary_expression assignment_operator expression
    ;

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

代入の左オペランドは、変数、プロパティアクセス、インデクサーアクセス、またはイベントアクセスとして分類される式である必要があります。The left operand of an assignment must be an expression classified as a variable, a property access, an indexer access, or an event access.

=演算子は、単純代入演算子 と呼ばれます。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. これらの演算子は、2つのオペランドに対して指定された演算を実行し、結果の値を、左オペランドによって指定された変数、プロパティ、またはインデクサー要素に代入します。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.

+= -= 左オペランドとしてイベントアクセス式を持つおよび演算子は、イベント代入演算子 と呼ばれます。The += and -= operators with an event access expression as the left operand are called the event assignment operators. 左オペランドとしてイベントアクセスが有効な他の代入演算子はありません。No other assignment operator is valid with an event access as the left operand. イベント代入演算子の詳細については、「 イベントの割り当て」を参照してください。The event assignment operators are described in Event assignment.

代入演算子は、右から左にグループ化されます。The assignment operators are 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).

単純代入Simple assignment

=演算子は、単純代入演算子と呼ばれます。The = operator is called the simple assignment operator.

単純な代入の左オペランドがの形式である E.P か、または E[Ei] にコンパイル時の型がある場合 E dynamic 、代入は動的にバインドされます (動的バインド)。If the left operand of a simple assignment is of the form E.P or E[Ei] where E has the compile-time type dynamic, then the assignment is dynamically bound (Dynamic binding). この場合、代入式のコンパイル時の型は dynamic であり、以下に説明する解決方法は、の実行時の型に基づいて実行時に行われ E ます。In this case the compile-time type of the assignment expression is dynamic, and the resolution described below will take place at run-time based on the run-time type of E.

単純な代入では、右オペランドは左オペランドの型に暗黙的に変換できる式である必要があります。In a simple assignment, the right operand must be an expression that is implicitly convertible to the type of the left operand. 操作は、左オペランドによって指定された変数、プロパティ、またはインデクサー要素に右オペランドの値を割り当てます。The operation assigns the value of the right operand to the variable, property, or indexer element given by the left operand.

単純な代入式の結果は、左側のオペランドに割り当てられた値になります。The result of a simple assignment expression is the value assigned to the left operand. 結果は左オペランドと同じ型であり、常に値として分類されます。The result has the same type as the left operand and is always classified as a value.

左オペランドがプロパティまたはインデクサーアクセスの場合は、プロパティまたはインデクサーにアクセサーが必要 set です。If the left operand is a property or indexer access, the property or indexer must have a set accessor. そうでない場合は、バインド時エラーが発生します。If this is not the case, a binding-time error occurs.

フォームの単純な割り当ての実行時処理は、次の手順で構成されてい x = y ます。The run-time processing of a simple assignment of the form x = y consists o