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

SectionSection カテゴリCategory 演算子Operators
一次式Primary expressions PrimaryPrimary 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 シフトShift << >><< >>
関係演算子と型検査演算子Relational and type-testing operators 関係式と型検査Relational and type testing < > <= >= is as< > <= >= is as
関係演算子と型検査演算子Relational and type-testing operators 等価比較Equality == !=== !=
論理演算子Logical operators 論理 ANDLogical AND &
論理演算子Logical operators 論理 XORLogical XOR ^
論理演算子Logical operators 論理 ORLogical 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 = *= /= %= += -= <<= >>= &= ^= |= =>= *= /= %= += -= <<= >>= &= ^= |= =>

同じ優先順位を持つ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. 特に、メンバーアクセス、メソッド呼び出し、=&&||???:=>checkeduncheckednewtypeofdefaultasis の各演算子をオーバーロードすることはできません。In 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. たとえば、operator * のオーバーロードは、operator *=のオーバーロードでもあります。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 は、オーバーロード可能な単項演算子で、xX型の式で、次のように処理されます。An operation of the form op x or x op, where op is an overloadable unary operator, and x is an expression of type X, is processed as follows:

  • 操作 operator op(x) に対して 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:

  • 操作 operator op(x,y) に対して X および Y によって提供される一連の候補ユーザー定義演算子が決定されます。The set of candidate user-defined operators provided by X and Y for the operation operator op(x,y) is determined. このセットは、X によって提供される候補演算子と Yによって提供される候補演算子の和集合で構成されます。各演算子は、ユーザー定義演算子の候補の規則を使用して決定されます。The set consists of the union of the candidate operators provided by X and the candidate operators provided by Y, each determined using the rules of Candidate user-defined operators. XY が同じ型である場合、または XY が共通の基本型から派生している場合、共有候補の演算子は、結合されたセット内で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 は引数リストであるため、Toperator 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 はその基になる型であり、それ以外の場合は T0Tになります。If T is a nullable type, T0 is its underlying type, otherwise T0 is equal to T.
  • T0 内のすべての operator op 宣言、およびそのような演算子のすべてのリフトされた形式では、Aの引数リストに対して少なくとも1つの演算子 (適用可能な関数メンバー) が適用される場合、候補演算子のセットは 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.
  • それ以外の場合、T0object場合、候補演算子のセットは空になります。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の場合、bbytesshortであるため、オーバーロードの解決では最適な演算子として 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. したがって、bsintに変換され、結果の型は intになります。Thus, the effect is that b and s are converted to int, and the type of the result is int. 同様に、操作 i * dでは、iintddoubleであるため、オーバーロードの解決では、最適な演算子として 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. 単項数値の上位変換は、型 sbytebyteshortushort、または 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型に変換されるか、または他のオペランドが sbyteshortint、または 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 型で、もう一方のオペランドが sbyteshort、または 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.

最初のルールでは、decimal の種類と doublefloat の種類を混在させる操作は許可されていないことに注意してください。Note that the first rule disallows any operations that mix the decimal type with the double and float types. このルールは、decimal 型と doublefloat の型の間に暗黙的な変換がないという事実から、次のようになります。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);
}

decimaldoubleで乗算できないため、バインド時エラーが発生します。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. リフトされた演算子は、一方または両方のオペランドが null の場合に false 値を生成します。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.

型 T の  型パラメーターを K N 名前のメンバー参照は、次のように処理されます。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 が型パラメーターの場合、 Tのプライマリ制約またはセカンダリ制約 (型パラメーター制約) として指定された各型の N という名前のアクセス可能なメンバーのセットは、object内の N という名前のアクセス可能なメンバーのセットと共に結合されます。If T is a type parameter, then the set is the union of the sets of accessible members named N in each of the types specified as a primary constraint or secondary constraint (Type parameter constraints) for T, along with the set of accessible members named N in object.
    • それ以外の場合、このセットは、 T内の N という名前のすべてのアクセス可能な (メンバーアクセス) メンバーで構成されます。これには、継承されたメンバーや、object内の N という名前のアクセス可能Otherwise, the set consists of all accessible (Member access) members named N in T, including inherited members and the accessible members named N in object. T が構築された型である場合は、「構築された型のメンバー」で説明されているように、型引数を置き換えることによってメンバーのセットを取得します。If T is a constructed type, the set of members is obtained by substituting type arguments as described in Members of constructed types. override 修飾子を含むメンバーは、セットから除外されます。Members that include an override modifier are excluded from the set.
  • 次に、K がゼロの場合、宣言に型パラメーターを含む入れ子になったすべての型が削除されます。Next, if K is zero, all nested types whose declarations include type parameters are removed. K がゼロでない場合は、型パラメーターの数が異なるメンバーがすべて削除されます。If K is not zero, all members with a different number of type parameters are removed. K がゼロの場合、型パラメーターを持つメソッドは削除されません。これは、型の推論プロセス (型の推定) が型引数を推論できる可能性があるためです。Note that when K is zero, methods having type parameters are not removed, since the type inference process (Type inference) might be able to infer the type arguments.
  • 次に、メンバーが呼び出されると、invocable以外のすべてのメンバーがセットから削除されます。Next, if the member is invoked, all non-invocable members are removed from the set.
  • 次に、他のメンバーによって非表示になっているメンバーがセットから削除されます。Next, members that are hidden by other members are removed from the set. Set 内のすべてのメンバー S.M について、S はメンバー M が宣言されている型であるため、次の規則が適用されます。For every member S.M in the set, where S is the type in which the member M is declared, the following rules are applied:
    • M が定数、フィールド、プロパティ、イベント、または列挙型のメンバーである場合は、S の基本型で宣言されたすべてのメンバーがセットから削除されます。If M is a constant, field, property, event, or enumeration member, then all members declared in a base type of S are removed from the set.
    • M が型宣言の場合、S の基本型で宣言されているすべての非型は、セットから削除され、S の基本型で宣言された M と同じ数の型パラメーターを持つすべての型宣言は、セットから削除されます。If M is a type declaration, then all non-types declared in a base type of S are removed from the set, and all type declarations with the same number of type parameters as M declared in a base type of S are removed from the set.
    • M がメソッドの場合、S の基本型で宣言されているすべての非メソッドメンバーがセットから削除されます。If M is a method, then all non-method members declared in a base type of S are removed from the set.
  • 次に、クラスメンバーによって隠ぺいされたインターフェイスメンバーがセットから削除されます。Next, interface members that are hidden by class members are removed from the set. このステップは、T が型パラメーターであり、object 以外の有効な基本クラスと、空でない有効なインターフェイスセット (型パラメーター制約) の両方が T 場合にのみ効果があります。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). Set 内のすべてのメンバー S.M について、S はメンバー M が宣言されている型であるため、Sobject以外のクラス宣言の場合、次の規則が適用されます。For every member S.M in the set, where S is the type in which the member M is declared, the following rules are applied if S is a class declaration other than object:
    • M が定数、フィールド、プロパティ、イベント、列挙型のメンバー、または型の宣言である場合、インターフェイス宣言で宣言されているすべてのメンバーがセットから削除されます。If M is a constant, field, property, event, enumeration member, or type declaration, then all members declared in an interface declaration are removed from the set.
    • M がメソッドの場合は、インターフェイス宣言で宣言されているすべての非メソッドメンバーがセットから削除され、インターフェイス宣言で宣言された M と同じシグネチャを持つすべてのメソッドがセットから削除されます。If M is a method, then all non-method members declared in an interface declaration are removed from the set, and all methods with the same signature as M declared in an interface declaration are removed from the set.
  • 最後に、非表示のメンバーを削除すると、参照の結果が決定されます。Finally, having removed hidden members, the result of the lookup is determined:
    • セットが、メソッドではない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.EnumSystem.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 および objectのクラス型です。If T is a struct_type, the base types of T are the class types System.ValueType and object.
  • Tclass_typeの場合、T の基本型は、クラス型 objectを含む Tの基本クラスです。If T is a class_type, the base types of T are the base classes of T, including the class type object.
  • Tinterface_typeの場合、T の基本型は T の基本インターフェイスであり、クラス型 objectです。If T is an interface_type, the base types of T are the base interfaces of T and the class type object.
  • Tarray_typeの場合、T の基本型は System.Array および objectのクラス型です。If T is an array_type, the base types of T are the class types System.Array and object.
  • Tdelegate_typeの場合、T の基本型は System.Delegate および objectのクラス型です。If 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
  • EventsEvents
  • インデクサー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. テーブルでは、exy、および 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) オーバーロードの解決は、クラスまたは構造体 TF 最適なメソッドを選択するために適用されます。Overload resolution is applied to select the best method F in the class or struct T. メソッドが staticない場合、バインド時エラーが発生します。A binding-time error occurs if the method is not static. (x,y)引数リストを使用してメソッドが呼び出されます。The method is invoked with the argument list (x,y).
e.F(x,y) オーバーロードの解決は、eの型によって指定されたクラス、構造体、またはインターフェイスで最適なメソッド F を選択するために適用されます。Overload resolution is applied to select the best method F in the class, struct, or interface given by the type of e. メソッドが static場合、バインド時エラーが発生します。A binding-time error occurs if the method is static. インスタンス式 e と引数リスト (x,y)を使用してメソッドが呼び出されます。The method is invoked with the instance expression e and the argument list (x,y).
「プロパティ アクセス」Property access P 含んでいるクラスまたは構造体のプロパティ Pget アクセサーが呼び出されます。The get accessor of the property P in the containing class or struct is invoked. P が書き込み専用の場合は、コンパイル時にエラーが発生します。A compile-time error occurs if P is write-only. Pstaticされていない場合、インスタンス式は thisます。If P is not static, the instance expression is this.
P = value 含んでいるクラスまたは構造体のプロパティ Pset アクセサーは (value)引数リストを使用して呼び出されます。The set accessor of the property P in the containing class or struct is invoked with the argument list (value). P が読み取り専用の場合、コンパイル時エラーが発生します。A compile-time error occurs if P is read-only. Pstaticされていない場合、インスタンス式は thisます。If P is not static, the instance expression is this.
T.P クラスまたは構造体 TP プロパティの get アクセサーが呼び出されます。The get accessor of the property P in the class or struct T is invoked. Pstatic されていない場合、または P が書き込み専用の場合、コンパイル時エラーが発生します。A compile-time error occurs if P is not static or if P is write-only.
T.P = value クラスまたは構造体 T 内のプロパティ Pset アクセサーが、(value)の引数リストを使用して呼び出されます。The set accessor of the property P in the class or struct T is invoked with the argument list (value). Pstatic されていない場合、または P が読み取り専用の場合、コンパイル時エラーが発生します。A compile-time error occurs if P is not static or if P is read-only.
e.P e の型によって指定されたクラス、構造体、またはインターフェイス内のプロパティ Pget アクセサーは、インスタンス式 eを使用して呼び出されます。The get accessor of the property P in the class, struct, or interface given by the type of e is invoked with the instance expression e. Pstatic 場合、または P が書き込み専用の場合、バインド時エラーが発生します。A binding-time error occurs if P is static or if P is write-only.
e.P = value e の型によって指定されたクラス、構造体、またはインターフェイス内のプロパティ Pset アクセサーは、インスタンス式 e および引数リスト (value)を使用して呼び出されます。The set accessor of the property P in the class, struct, or interface given by the type of e is invoked with the instance expression e and the argument list (value). Pstatic 場合、または P が読み取り専用の場合、バインド時エラーが発生します。A binding-time error occurs if P is static or if P is read-only.
イベントアクセスEvent access E += value 含んでいるクラスまたは構造体のイベント Eadd アクセサーが呼び出されます。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 含んでいるクラスまたは構造体のイベント Eremove アクセサーが呼び出されます。The remove accessor of the event E in the containing class or struct is invoked. E が静的でない場合は、インスタンス式が thisます。If E is not static, the instance expression is this.
T.E += value クラスまたは構造体 T のイベント Eadd アクセサーが呼び出されます。The add accessor of the event E in the class or struct T is invoked. E が静的でない場合は、バインド時エラーが発生します。A binding-time error occurs if E is not static.
T.E -= value クラスまたは構造体 T のイベント Eremove アクセサーが呼び出されます。The remove accessor of the event E in the class or struct T is invoked. E が静的でない場合は、バインド時エラーが発生します。A binding-time error occurs if E is not static.
e.E += value e の型によって指定されたクラス、構造体、またはインターフェイス内のイベント Eadd アクセサーは、インスタンス式 eを使用して呼び出されます。The add accessor of the event E in the class, struct, or interface given by the type of e is invoked with the instance expression e. E が静的である場合、バインド時エラーが発生します。A binding-time error occurs if E is static.
e.E -= value e の型によって指定されたクラス、構造体、またはインターフェイス内のイベント Eremove アクセサーは、インスタンス式 eを使用して呼び出されます。The remove accessor of the event E in the class, struct, or interface given by the type of e is invoked with the instance expression e. E が静的である場合、バインド時エラーが発生します。A binding-time error occurs if E is static.
インデクサーへのアクセス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 オーバーロードの解決は、xyの型によって指定されたクラスまたは構造体の中で最適な二項演算子を選択するために適用されます。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.
  • イベントの場合、引数リストは、+= または -= 演算子の右オペランドとして指定された式で構成されます。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 arguments, 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 アクセサーを呼び出すときに、代入演算子の右オペランドとして指定された式が、set アクセサー宣言の暗黙的な value パラメーターに対応します。For indexers, when invoking the set accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit value parameter of the set accessor declaration.
  • プロパティの場合、get アクセサーを呼び出すときに引数はありません。For properties, when invoking the get accessor there are no arguments. set アクセサーを呼び出すと、代入演算子の右オペランドとして指定された式が、set アクセサー宣言の暗黙的な value パラメーターに対応します。When invoking the set accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit value parameter of the set accessor declaration.
  • ユーザー定義の単項演算子 (変換を含む) の場合、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 から Aへの暗黙的な参照変換が存在する場合に B[]です。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
    }
}

F の2回目の呼び出しでは、b の実際の要素の型が stringobjectではないため、System.ArrayTypeMismatchException がスローされます。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) 型の推論のタスクでは、呼び出し M<S1...Sn>(E1...Em) が有効になるように、型パラメーター X1...Xn ごとに一意の型引数 S1...Sn を検索します。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
  • それ以外の場合、EiU 型があり、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.
  • それ以外の場合、EiU 型があり、xiref または 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:

  • すべての未修正の型の変数は、(依存関係)に依存しないすべての Xj を修正 (修正) Xi ます。All unfixed type variables Xi which do not depend on (Dependence) any Xj are fixed (Fixing).
  • このような型の変数が存在しない場合は、Xi すべての未修正の型変数が固定され、次のすべての要素が保持されます。If no such type variables exist, all unfixed type variables Xi are fixed for which all of the following hold:
    • に依存する型変数 Xj が少なくとも1つあり 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.
  • それ以外の場合、出力の種類(出力型) には固定されていない型の変数が含まれていますが、入力の型 (入力型) には Xj の出力型の推論(出力型の推論) が EiからTi対して行われるので、すべての引数に対応するパラメーターの型 Ti Ei ます。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 のすべてのパラメーターの型は TE入力型になります。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 の戻り値の型は TEの出力型になります。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 型の引数 Tk Ek では、型 XjEk入力型Tk に発生し、Xi 型の Ek出力型で発生する場合があります。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.

XjXiに直接依存している場合、または XiXkに直接依存しており、XkXj依存している場合、XjXiに依存します。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

出力型の推論は、次のように TEから実行されます。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つのメソッドが生成 されます。Otherwise, if E is a method group and T is a delegate type or expression tree type with parameter types T1...Tk and return type Tb, and overload resolution of E with the types T1...Tk yields a single method with return type U, then a lower-bound inference is made from U to Tb.
  • それ以外の場合、EU型の式である場合、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

明示的なパラメーター型の推論は、次のように TEから作成されます。An explicit parameter type inference is made from an expression E to a type T in the following way:

  • E がパラメーターの U1...Uk 型を持つ明示的に型指定された匿名関数であり、TV1...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 が固定されていない Xi1 つである場合、UXiの完全な境界のセットに追加されます。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
    • VV1? 型で、U は型です U1?V is the type V1? and U is the type U1?
    • V は構築された型 C<V1...Vk>で、U は構築された型です C<U1...Uk>V is a constructed type C<V1...Vk>and U is a constructed type C<U1...Uk>

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

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

下限の推論Lower-bound inferences

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

  • V が未修正の Xi の1つである場合、UXiの下限のセットに追加されます。If V is one of the unfixed Xi then U is added to the set of lower bounds for Xi.

  • それ以外の場合、VV1?型で、UU1? 型である場合は、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

    • VIEnumerable<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 は、構築され U たクラス、構造体、インターフェイス、またはデリゲート型 C<V1...Vk>C<U1...Uk> あり、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> {}ケースインターフェイスでは、U1X または Yすることができるため、U から C<T> に推論するときに推論が行われないことを意味します)。(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
    • それ以外の場合、VC<V1...Vk> 場合、推論は Cの i 番目の型パラメーターに依存します。Otherwise, if V is C<V1...Vk> then inference depends on the i-th type parameter of C:
      • 共変の場合は、下限の推論が行われます。If it is covariant then a lower-bound inference is made.
      • 反変の場合は、上限の推論が行われます。If it is contravariant then an upper-bound inference is made.
      • 不変である場合は、正確な推定が行われます。If it is invariant then an exact inference is made.
  • それ以外の場合、推論は行われません。Otherwise, no inferences are made.

上限の推論Upper-bound inferences

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

  • V が固定されていない Xi1 つである場合、UXiの上限のセットに追加されます。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

    • UIEnumerable<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[]

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

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

      ("一意性" の制限は、interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}がある場合に C<U1> から V<Q>に推論するときに推論が行われないことを意味します。(The "uniqueness" restriction means that if we have interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}, then no inference is made when inferring from C<U1> to V<Q>. 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
    • それ以外の場合、UC<U1...Uk> 場合、推論は Cの i 番目の型パラメーターに依存します。Otherwise, if U is C<U1...Uk> then inference depends on the i-th type parameter of C:
      • 共変の場合は、上限の推論が行われます。If it is covariant then an upper-bound inference is made.
      • 反変の場合は、下限の推論が行われます。If it is contravariant then a lower-bound inference is made.
      • 不変である場合は、正確な推定が行われます。If it is invariant then an exact inference is made.
  • それ以外の場合、推論は行われません。Otherwise, no inferences are made.

写真のFixing

一連の境界を持つ固定されていない型変数Xi は、次のように固定されています。An unfixed type variable Xi with a set of bounds is fixed as follows:

  • 候補の種類のセット UjXiの一連の境界内のすべての型のセットとして開始されます。The set of candidate types Uj starts out as the set of all types in the set of bounds for Xi.
  • 次に、それぞれのバインドされている Xi を確認します。 Xi の完全バインド U については、U と同じではないすべての型 Uj を候補セットから削除します。We then examine each bound for Xi in turn: For each exact bound U of Xi all types Uj which are not identical to U are removed from the candidate set. Xi の下限 U ごとに、U からの暗黙の変換が行われていないすべての型 Uj 候補セットから削除されます。For each lower bound U of Xi all types Uj to which there is not an implicit conversion from U are removed from the candidate set. U への暗黙的な変換が行われていないすべての型 Uj Xi の上限 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 がある場合、XiVに固定されます。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.
  • それ以外の場合、Fに対して結果の型を推論することはできません。Otherwise, 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.
  • それ以外の場合、Fの戻り値の型を推論することはできません。Otherwise a return type cannot be inferred for F.

匿名関数を含む型推論の例として、System.Linq.Enumerable クラスで宣言された Select 拡張メソッドを考えてみます。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 句を使用してインポートされ、string型の Name プロパティを持つクラス Customer された場合、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 引数は、Customerする T を推論する source パラメーターに関連付けられています。First, the customers argument is related to the source parameter, inferring T to be Customer. 次に、上記で説明した匿名関数型推論プロセスを使用して、c に型 Customerを指定し、式 c.Nameselector パラメーターの戻り値の型に関連付けて、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 パラメーターに関連付けられ、stringする X を推論します。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.TotalSecondsf2の戻り値の型に関連付けられ、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>

は、Dと互換性のある (デリゲート宣言) になります。becomes 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.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.In particular, there are no anonymous functions and hence no need for multiple phases of inference.

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.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. If for any of the Xi no bounds were found, type inference fails.If for any of the Xi no bounds were found, type inference fails. Otherwise, all Xi are fixed to corresponding Si, which are the result of type inference.Otherwise, all Xi are fixed to corresponding Si, which are the result of type inference.

Finding the best common type of a set of expressionsFinding 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 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.In particular, the element types of implicitly typed arrays and the return types of anonymous functions with block bodies are found in this way.

Intuitively, given a set of expressions E1...Em this inference should be equivalent to calling a methodIntuitively, given a set of expressions E1...Em this inference should be equivalent to calling a method

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

with the Ei as arguments.with the Ei as arguments.

More precisely, the inference starts out with an unfixed type variable X.More precisely, the inference starts out with an unfixed type variable X. Output type inferences are then made from each Ei to X.Output type inferences are then made from each Ei to X. Finally, X is fixed and, if successful, the resulting type S is the resulting best common type for the expressions.Finally, X is fixed and, if successful, the resulting type S is the resulting best common type for the expressions. If no such S exists, the expressions have no best common type.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.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. Overload resolution selects the function member to invoke in the following distinct contexts within 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.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. 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).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: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.Given the set of applicable candidate function members, the best function member in that set is located. If the set contains only one function member, then that function member is the best function member.If the set contains only one function member, then that function member is the best function member. Otherwise, the best function member is the one function member that is better than all other function members with respect to the given argument list, provided that each function member is compared to all other function members using the rules in Better function member.Otherwise, the best function member is the one function member that is better than all other function members with respect to the given argument list, provided that each function member is compared to all other function members using the rules in Better function member. If there is not exactly one function member that is better than all other function members, then the function member invocation is ambiguous and a binding-time error occurs.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.The following sections define the exact meanings of the terms applicable function member and better function member.

Applicable function memberApplicable function member

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 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の引数ごとに、引数のパラメーター渡しモード (つまり、value、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 引数の式 {E1, E2, ..., En} と、適用可能な2つの関数メンバー Mp Mq およびパラメーターの型 {P1, P2, ..., Pn}{Q1, Q2, ..., Qn}に対して指定されている場合、MpMq よりも適切な関数メンバーとして定義されています。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 から Pxへの暗黙的な変換よりも適切ではありません。for 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 に対応する Qiへの id 変換がある場合)、より適切な関数メンバーを決定するために、次のような相互に関連する規則が順番に適用されます。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 が非ジェネリックメソッドで Mq がジェネリックメソッドである場合、MpMqよりも優れています。If Mp is a non-generic method and Mq is a generic method, then Mp is better than Mq.
  • それ以外の場合、Mp が通常の形式で適用可能で Mq params 配列を持ち、その拡張フォームにのみ適用できる場合、MpMqよりも優れています。Otherwise, if Mp is applicable in its normal form and Mq has a params array and is applicable only in its expanded form, then Mp is better than Mq.
  • それ以外の場合、MpMqよりも宣言されたパラメーターを持つ場合、MpMqよりも優れています。Otherwise, if Mp has more declared parameters than Mq, then Mp is better than Mq. これは、両方のメソッドが params 配列を持ち、拡張されたフォームにのみ適用できる場合に発生する可能性があります。This can occur if both methods have params arrays and are applicable only in their expanded forms.
  • それ以外の場合、Mp のすべてのパラメーターに対応する引数があるのに対し、既定の引数は Mq で少なくとも1つの省略可能なパラメーターの代わりに使用する必要があり、MpMqよりも優れています。Otherwise if all parameters of Mp have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in Mq then Mp is better than Mq.
  • それ以外の場合、Mp のパラメーターの型が Mqよりも多い場合、MpMqよりも優れています。Otherwise, if Mp has more specific parameter types than Mq, then Mp is better than Mq. {R1, R2, ..., Rn}{S1, S2, ..., Sn} は、MpMqのインスタンスおよび展開されていないパラメーターの種類を表します。Let {R1, R2, ..., Rn} and {S1, S2, ..., Sn} represent the uninstantiated and unexpanded parameter types of Mp and Mq. Mpのパラメーターの型は、各パラメーターについては Mqよりも具体的で、RxSxよりも限定的ではなく、少なくとも1つのパラメーターについては Rx よりも Sxよりも具体的です。Mp's parameter types are more specific than Mq's if, for each parameter, Rx is not less specific than Sx, and, for at least one parameter, Rx is more specific than Sx:
    • 型パラメーターが非型パラメーターよりも限定的ではありません。A type parameter is less specific than a non-type parameter.
    • 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

式の E から型 T1に変換する暗黙的な C1 変換と、式の E を型 T2に変換する暗黙的な変換 C2 を指定した場合、C1C2 と完全に一致せず、次の少なくとも1つのが保持されていると、E よりも変換が適切になります。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

E と型 Tが指定されている場合、次のいずれかの条件を満たしている場合は T に正確に一致 E ます。Given an expression E and a type T, E exactly matches T if one of the following holds:

  • E には S型があり、S からに id 変換が存在し TE has a type S, and an identity conversion exists from S to T
  • E は匿名関数 T であり、デリゲート型 D または式ツリー型 Expression<D> で、次のいずれかが保持されます。E is an anonymous function, T is either a delegate type D or an expression tree type Expression<D> and one of the following holds:
    • D (推定戻り値の型) のパラメーターリストのコンテキストで E に対して推論された戻り値の型 X 存在します。また、X からの戻り値の型への 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 が async で、D の戻り値の型が Task<Y>である場合、次のいずれかが保持されます。Either E is non-async and D has a return type Y or E is async and D has a return type Task<Y>, and one of the following holds:
      • E の本体は、正確に一致する式です YThe body of E is an expression that exactly matches Y
      • E の本体は、すべての return ステートメントが正確に一致する式を返すステートメントブロックです YThe body of E is a statement block where every return statement returns an expression that exactly matches Y

変換ターゲットの向上Better conversion target

T1T2の2つの異なる型を指定した場合、T2 から T1 への暗黙的な変換が存在せず、少なくとも次のいずれかが保持されている場合、T1T2 よりも変換ターゲットとして適しています。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 から T2 への暗黙的な変換An implicit conversion from T1 to T2 exists
  • T1 はデリゲート型 D1 または式ツリー型 Expression<D1>のいずれかで、T2 はデリゲート型 D2 または式ツリー型 Expression<D2>D1 には戻り値の型 S1、次のいずれかが含まれます。T1 is either a delegate type D1 or an expression tree type Expression<D1>, T2 is either a delegate type D2 or an expression tree type Expression<D2>, D1 has a return type S1 and one of the following holds:
    • D2 は void を返します。D2 is void returning
    • D2S2戻り値の型があり、S1 がより適切な変換ターゲットです 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 が符号付き整数型であり、T2 が符号なし整数型である S2 または S2? である場合に S1 または S1? ます。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 で、S2byteushortuint、または ulongS1 is sbyte and S2 is byte, ushort, uint, or ulong
    • S1short で、S2ushortuint、または ulongS1 is short and S2 is ushort, uint, or ulong
    • S1intS2uint、または ulongS1 is int and S2 is uint, or ulong
    • S1longS2ulongS1 is long and S2 is ulong

オーバーロード (ジェネリッククラスでの)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. 一時変数は、M内の this としてアクセスできますが、他の方法ではアクセスできません。The temporary variable is accessible as this within M, but not in any other way. したがって、E が真の変数である場合にのみ、呼び出し元は thisする M の変更を観察できます。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.
    • E の型がvalue_typeである場合、E を型 objectに変換するためのボックス変換 (ボックス化変換) が実行され、E は次の手順では object 型と見なされます。If the type of E is a value_type, a boxing conversion (Boxing conversions) is performed to convert E to type object, and E is considered to be of type object in the following steps. この場合、MSystem.Objectのメンバーである必要があります。In this case, M could only be a member of System.Object.
    • E の値が有効であるかどうかがチェックされます。The value of E is checked to be valid. E の値が null場合は System.NullReferenceException がスローされ、それ以上の手順は実行されません。If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.
    • 呼び出す関数メンバーの実装は、次のように決定されます。The function member implementation to invoke is determined:
      • E のバインド時の型がインターフェイスの場合、呼び出す関数メンバーは Eによって参照されるインスタンスの実行時の型によって提供される M の実装です。If the binding-time type of E is an interface, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. この関数メンバーは、Eによって参照されるインスタンスのランタイム型によって提供される M の実装を決定するために、インターフェイスマッピング規則 (インターフェイスマッピング) を適用することによって決定されます。This function member is determined by applying the interface mapping rules (Interface mapping) to determine the implementation of M provided by the run-time type of the instance referenced by E.
      • それ以外の場合、M が仮想関数メンバーである場合、呼び出す関数メンバーは Eによって参照されるインスタンスの実行時の型によって提供される M の実装です。Otherwise, if M is a virtual function member, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. この関数メンバーは、Eによって参照されるインスタンスの実行時の型に対して、M の最も派生する実装 (仮想メソッド) を決定するための規則を適用することによって決定されます。This function member is determined by applying the rules for determining the most derived implementation (Virtual methods) of M with respect to the run-time type of the instance referenced by E.
      • それ以外の場合、M は非仮想関数メンバーであり、呼び出す関数メンバーは M ます。Otherwise, M is a non-virtual function member, and the function member to invoke is M itself.
    • 上記の手順で決定した関数メンバーの実装が呼び出されます。The function member implementation determined in the step above is invoked. E によって参照されるオブジェクトは、thisによって参照されるオブジェクトになります。The object referenced by E becomes the object referenced by this.

ボックス化されたインスタンスでの呼び出しInvocations on boxed instances

Value_typeに実装されている関数メンバーは、次のような場合にvalue_typeのボックス化されたインスタンスを使用して呼び出すことができます。A function member implemented in a value_type can be invoked through a boxed instance of that value_type in the following situations:

  • 関数メンバーが object 型から継承されたメソッドの override であり、object型のインスタンス式を通じて呼び出される場合。When the function member is an override of a method inherited from type object and is invoked through an instance expression of type object.
  • 関数メンバーがインターフェイス関数メンバーの実装であり、 interface_typeのインスタンス式を通じて呼び出される場合。When the function member is an implementation of an interface function member and is invoked through an instance expression of an interface_type.
  • デリゲートを通じて関数メンバーが呼び出されたとき。When the function member is invoked through a delegate.

このような場合、ボックス化されたインスタンスには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_expressions とprimary_no_array_creation_expressionの間で分けられます。Primary expressions are divided between array_creation_expressions and primary_no_array_creation_expressions. この方法で配列作成式を扱うことは、他の単純な式フォームと共にリストするのではなく、文法によって、次のような混乱の可能性のあるコードを許可しないようにします。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.

書式指定文字列リテラルは次のように構成されます。ここで Ninterpolated_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
    • 次に、0 から N-1I 数値ごとに、次のように入力します。Then for each number I from 0 to N-1:
      • I の10進数表現The 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 がゼロでsimple_nameブロック内に存在し、ブロックの (またはそれを囲むブロックの) ローカル変数宣言領域 (宣言) に、 Iという名前のローカル変数、パラメーター、または定数が含まれている場合、 simple_nameはそのローカル変数、パラメーター、または定数を参照し、変数または値として分類されます。If K is zero and the simple_name appears within a block and if the block's (or an enclosing block's) local variable declaration space (Declarations) contains a local variable, parameter or constant with name I, then the simple_name refers to that local variable, parameter or constant and is classified as a variable or value.

  • K がゼロで、 simple_nameがジェネリックメソッド宣言の本体内に存在し、その宣言に Iという名前の型パラメーターが含まれている場合、 simple_nameはその型パラメーターを参照します。If K is zero and the simple_name appears within the body of a generic method declaration and if that declaration includes a type parameter with name I, then the simple_name refers to that type parameter.

  • それ以外の場合は、インスタンス型 T (インスタンス型) に対して、すぐ外側の型宣言のインスタンス型から開始し、外側の各クラスまたは構造体宣言のインスタンス型 (存在する場合) を続行します。Otherwise, for each instance type T (The instance type), starting with the instance type of the immediately enclosing type declaration and continuing with the instance type of each enclosing class or struct declaration (if any):

    • K がゼロで、T の宣言に Iという名前の型パラメーターが含まれている場合、 simple_nameはその型パラメーターを参照します。If K is zero and the declaration of T includes a type parameter with name I, then the simple_name refers to that type parameter.
    • それ以外の場合、K 型引数を使用して T 内の I のメンバー参照 (メンバー参照) が一致すると、次のようになります。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 がゼロで、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が名前空間宣言に含まれている場合、 * I* はあいまいで、コンパイル時エラーが発生します。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_nameN内の I という名前空間を参照します。Otherwise, the simple_name refers to the namespace named I in N.
    • それ以外の場合、N に名前 IK 型パラメーターを持つアクセス可能な型が含まれている場合は、次のようになります。Otherwise, if N contains an accessible type having name I and K type parameters, then:
      • K がゼロで、 simple_nameが発生した場所が N の名前空間宣言によって囲まれており、名前空間を名前空間または型に関連付けるextern_alias_directiveまたはusing_alias_directiveが名前空間宣言に含まれている場合、 * I* はあいまいで、コンパイル時エラーが発生します。If K is zero and the location where the simple_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the simple_name is ambiguous and a compile-time error occurs.
      • それ以外の場合、 namespace_or_type_nameは、指定された型引数を使用して構築された型を参照します。Otherwise, the namespace_or_type_name refers to the type constructed with the given type arguments.
    • それ以外の場合、 simple_nameが発生した場所が Nの名前空間宣言によって囲まれている場合は、次のようになります。Otherwise, if the location where the simple_name occurs is enclosed by a namespace declaration for N:
      • K がゼロで、名前空間の宣言に、名前 I をインポートした名前空間または型に関連付けるextern_alias_directiveまたはusing_alias_directiveが含まれている場合、 simple_nameはその名前空間または型を参照します。If K is zero and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with an imported namespace or type, then the simple_name refers to that namespace or type.
      • それ以外の場合、 using_namespace_directives および名前空間宣言のusing_static_directiveによってインポートされた名前空間と型の宣言に、アクセス可能な型または非拡張静的メンバーが1つだけ含まれており、その名前が I で、型 * * パラメーターが K場合は、指定された型引数を使用して構築されたその型またはメンバーをOtherwise, if the namespaces and type declarations imported by the using_namespace_directives and using_static_directives of the namespace declaration contain exactly one accessible type or non-extension static member having name I and K type parameters, then the simple_name refers to that type or member constructed with the given type arguments.
      • それ以外の場合、名前空間宣言のusing_namespace_directives によってインポートされた名前空間と型に複数のアクセス可能な型または非拡張メソッドの静的メンバーが含まれていて、名前が I で、型パラメーターが  K場合、 simple_nameはあいまいで、エラーが発生します。Otherwise, if the namespaces and types imported by the using_namespace_directives of the namespace declaration contain more than one accessible type or non-extension-method static member having name I and K type parameters, then the simple_name is ambiguous and an error occurs.

    この手順全体は、 namespace_or_type_name (名前空間と型名) を処理するための対応する手順と完全に並列であることに注意してください。Note that this entire step is exactly parallel to the corresponding step in the processing of a namespace_or_type_name (Namespace and type names).

  • それ以外の場合、 simple_nameは定義されていないため、コンパイル時エラーが発生します。Otherwise, the simple_name is undefined and a compile-time error occurs.

かっこで囲まれる式Parenthesized expressions

Parenthesized_expressionは、かっこで囲まれたで構成されます。A parenthesized_expression consists of an expression enclosed in parentheses.

parenthesized_expression
    : '(' expression ')'
    ;

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.

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

  • 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 が型パラメーターではなく、IE のメンバー参照 (メンバー参照) が 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).
    • Istatic プロパティを識別する場合、結果は、インスタンス式が関連付けられていないプロパティアクセスになります。If I identifies a static property, then the result is a property access with no associated instance expression.
    • Istatic フィールドを識別する場合は、次のようになります。If I identifies a static field:
      • フィールドが readonly、フィールドが宣言されているクラスまたは構造体の静的コンストラクターの外側で参照が発生した場合、結果は値になります。つまり、 Eの静的フィールド I の値です。If the field is readonly and the reference occurs outside the static constructor of the class or struct in which the field is declared, then the result is a value, namely the value of the static field I in E.
      • それ以外の場合、結果は変数になります。つまり、 Eの静的フィールド I です。Otherwise, the result is a variable, namely the static field I in E.
    • Istatic イベントを識別する場合:If I identifies a static event:
      • イベントが宣言されているクラスまたは構造体内で参照が発生し、イベントがevent_accessor_declarations (イベント) を使用せずに宣言されている場合、E.II が静的フィールドであった場合とまったく同じように処理されます。If the reference occurs within the class or struct in which the event is declared, and the event was declared without event_accessor_declarations (Events), then E.I is processed exactly as if I were a static field.
      • それ以外の場合、結果はインスタンス式が関連付けられていないイベントアクセスになります。Otherwise, the result is an event access with no associated instance expression.
    • I が定数を識別する場合、結果は値、つまりその定数の値になります。If I identifies a constant, then the result is a value, namely the value of that constant.
    • I が列挙型のメンバーを識別する場合、結果はその列挙体のメンバーの値、つまり値になります。If I identifies an enumeration member, then the result is a value, namely the value of that enumeration member.
    • それ以外の場合、E.I は無効なメンバー参照であり、コンパイル時エラーが発生します。Otherwise, E.I is an invalid member reference, and a compile-time error occurs.
  • E がプロパティアクセス、インデクサーアクセス、変数、または値であり、その型が Tである場合、および K 型引数を持つ T 内の I のメンバー参照 (メンバー参照) によって一致が生成されると、E.I が評価され、次のように分類されます。If E is a property access, indexer access, variable, or value, the type of which is T, and a member lookup (Member lookup) of I in T with K type arguments produces a match, then E.I is evaluated and classified as follows:
    • 最初に、E がプロパティまたはインデクサーアクセスである場合は、プロパティまたはインデクサーアクセスの値 (式の値) を取得し、E を値として再分類します。First, if E is a property or indexer access, then the value of the property or indexer access is obtained (Values of expressions) and E is reclassified as a value.
    • I が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,
      • Ethis場合、I は自動的に実装されるプロパティ (自動的に実装されるプロパティ) を setter を指定せずに識別します。参照は、クラスまたは構造体の T型のインスタンスコンストラクター内で行われます。その後、結果は変数になります。つまり、I によって指定された T によって指定された自動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、参照がフィールドが宣言されているクラスのインスタンスコンストラクターの外部で発生した場合、結果は値になります。つまり、 Eによって参照されるオブジェクト内のフィールド I の値です。Otherwise, if the field is readonly and the reference occurs outside an instance constructor of the class in which the field is declared, then the result is a value, namely the value of the field I in the object referenced by E.
      • それ以外の場合、結果は変数、つまり Eによって参照されるオブジェクト内のフィールド I になります。Otherwise, the result is a variable, namely the field I in the object referenced by E.
    • Tstruct_typeで、I struct_typeのインスタンスフィールドを識別する場合は、次のようになります。If T is a struct_type and I identifies an instance field of that struct_type:
      • E が値の場合、またはフィールドが readonly で、そのフィールドが宣言されている構造体のインスタンスコンストラクターの外側で参照が発生した場合、結果は値になります。つまり、 Eによって指定された構造体のインスタンスコンストラクター内のフィールド I の値になります。If E is a value, or if the field is readonly and the reference occurs outside an instance constructor of the struct in which the field is declared, then the result is a value, namely the value of the field I in the struct instance given by E.
      • それ以外の場合、結果は変数、つまり Eによって指定された構造体インスタンス内のフィールド I になります。Otherwise, the result is a variable, namely the field I in the struct instance given by E.
    • I がインスタンスイベントを識別する場合は、次のようになります。If I identifies an instance event:
      • イベントが宣言されているクラスまたは構造体内で参照が発生し、イベントがevent_accessor_declarations (イベント) なしで宣言されており、参照が += または -= 演算子の左側として発生していない場合、E.II がインスタンスフィールドである場合とまったく同じように処理されます。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.Iフォームのメンバーアクセスでは、E が単一の識別子であり、 simple_name (簡易名) としての E の意味が、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. I は常に E 型のメンバーである必要があるため、E.I の2つの意味があいまいになることはありません。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));

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

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

x = F < A > +y;

は、 type_argument_listの後に二項プラス演算子が続くsimple_nameとしてではなく x = (F < A) > (+y)に記述されているかのように、小なり演算子、大なり演算子、および単項プラス演算子として解釈されます。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の意味を判断するために、実行時に実行時に適用されます。これには、コンパイル時の型 dynamicを持つprimary_expressionおよび引数のコンパイル時の型ではなく、実行時の型が使用されます。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_expressionvoidを返すメソッドまたはデリゲートを呼び出すと、結果は 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. さらに、Cobject以外のクラス型である場合は、インターフェイス型で宣言されたすべてのメソッドがセットから削除されます。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:

  • 非ジェネリックの非入れ子クラスである CiCi is a non-generic, non-nested class
  • Mj の名前は識別子ですThe name of Mj is identifier
  • 上に示すように、引数に静的メソッドとして適用すると、Mj にアクセスして適用できます。Mj is accessible and applicable when applied to the arguments as a static method as shown above
  • 暗黙的な 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:
    • 指定された名前空間またはコンパイル単位に、対象となる拡張メソッド MjCi 非ジェネリック型宣言が直接含まれている場合、これらの拡張メソッドのセットは候補セットになります。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によってインポートされた名前空間で直接宣言されている場合、適切な拡張メソッド Mjが直接含まれているため、これらの拡張メソッドのセットは候補セットになります。If types Ci imported by using_static_declarations and directly declared in namespaces imported by using_namespace_directives in the given namespace or compilation unit directly contain eligible extension methods Mj, then the set of those extension methods is the candidate set.
  • 外側の名前空間宣言またはコンパイル単位で候補セットが見つからない場合、コンパイル時エラーが発生します。If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs.
  • それ以外の場合は、「(オーバーロードの解決)」の説明に従って、オーバーロードの解決が候補セットに適用されます。Otherwise, overload resolution is applied to the candidate set as described in (Overload resolution). 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.GC.Gよりも優先され、E.FD.FC.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 arguments, separated by commas.

element_access
    : primary_no_array_creation_expression '[' expression_list ']'
    ;

Element_accessargument_listref または out 引数を含めることはできません。The 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の意味を判断するために、実行時に実行時に適用されます。これには、コンパイル時の型 dynamicを持つprimary_no_array_creation_expressionおよびargument_list式のコンパイル時の型ではなく、ランタイム型が使用されます。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のランクと同じである必要があります。また、各式は intuintlongulongの型であるか、またはこれらの型の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]フォームへの配列アクセスの実行時処理では、Parray_typeprimary_no_array_creation_expressionであり、Aargument_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. 各インデックス式を評価すると、次のいずれかの型への暗黙的な変換 (暗黙の変換) が実行されます: intuintlongulongFollowing evaluation of each index expression, an implicit conversion (Implicit conversions) to one of the following types is performed: int, uint, long, ulong. 暗黙的な変換が存在する、この一覧の最初の型が選択されます。The first type in this list for which an implicit conversion exists is chosen. たとえば、インデックス式が short 型の場合、int への暗黙的な変換が実行されます。これは、short から int への暗黙の変換と 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 はクラス、構造体、またはインターフェイス型 Tprimary_no_array_creation_expressionであり、Aargument_listで、次の手順で構成されます。The binding-time processing of an indexer access of the form P[A], where P is a primary_no_array_creation_expression of a class, struct, or interface type T, and A is an argument_list, consists of the following steps:

  • T によって提供されるインデクサーのセットが構築されます。The set of indexers provided by T is constructed. このセットは、T で宣言されたすべてのインデクサーと、override 宣言ではなく、現在のコンテキスト (メンバーアクセス) でアクセスできる T の基本型で構成されます。The set consists of all indexers declared in T or a base type of T that are not override declarations and are accessible in the current context (Member access).
  • このセットは、他のインデクサーによって適用可能で非表示にされるインデクサーに限定されます。The set is reduced to those indexers that are applicable and not hidden by other indexers. 次の規則は、セット内の各インデクサー S.I に適用されます。 S は、インデクサー I が宣言されている型です。The following rules are applied to each indexer S.I in the set, where S is the type in which the indexer I is declared:
    • IA (該当する関数メンバー) に対して適用されない場合は、I がセットから削除されます。If I is not applicable with respect to A (Applicable function member), then I is removed from the set.
    • IA (適用可能な関数メンバー) に対して適用できる場合、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 (適用可能な関数メンバー) に対して適用可能で、Sobject以外のクラス型である場合、インターフェイスで宣言されているすべてのインデクサーがセットから削除されます。If I is applicable with respect to A (Applicable function member) and S is a class type other than object, all indexers declared in an interface are removed from the set.
  • 結果として得られる一連のインデクサーが空の場合、適用可能なインデクサーは存在せず、バインド時エラーが発生します。If the resulting set of candidate indexers is empty, then no applicable indexers exist, and a binding-time error occurs.
  • 一連の候補インデクサーの最適なインデクサーは、オーバーロード解決のオーバーロードの解決規則を使用して識別されます。The best indexer of the set of candidate indexers is identified using the overload resolution rules of Overload resolution. 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:

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

上記以外のコンテキストでprimary_expression内の this を使用すると、コンパイル時エラーが発生します。Use of this in a primary_expression in a context other than the ones listed above is a compile-time error. 特に、静的メソッド、静的プロパティアクセサー、またはフィールド宣言のvariable_initializerthis を参照することはできません。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.Ibase[E]base_access式が ((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.Ibase[E]this.Ithis[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. 呼び出される関数メンバーを決定するには、関数メンバーの最も派生された実装 (仮想メソッド) を検索します。これは、thisの実行時の型に対してではなく、B に対して行われます。これは、非基本アクセスの場合と同様です。The function member that is invoked is determined by finding the most derived implementation (Virtual methods) of the function member with respect to B (instead of with respect to the run-time type of this, as would be usual in a non-base access). したがって、virtual 関数メンバーの override 内では、 base_accessを使用して、関数メンバーの継承された実装を呼び出すことができます。Thus, within an override of a virtual function member, a base_access can be used to invoke the inherited implementation of the function member. Base_accessによって参照される関数メンバーが 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.

後置インクリメントまたはデクリメント演算のオペランドがプロパティまたはインデクサーアクセスの場合、プロパティまたはインデクサーには、getset の両方のアクセサーが必要です。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. 定義済みの ++-- の演算子は、sbytebyteshortushortintuintlongulongcharfloatdoubledecimal、列挙型の各型に存在します。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:
    • インスタンス式 (xstaticでない場合) と 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.
    • xget アクセサーが呼び出され、戻り値が保存されます。The get accessor of x is invoked and the returned value is saved.
    • 選択した演算子は、引数として x の保存値を使用して呼び出されます。The selected operator is invoked with the saved value of x as its argument.
    • xset アクセサーは、value 引数として演算子によって返された値を使用して呼び出されます。The set accessor of x is invoked with the value returned by the operator as its value argument.
    • x の保存された値は、操作の結果になります。The saved value of x becomes the result of the operation.

++ 演算子と -- 演算子では、プレフィックスのインクリメントとデクリメント演算子もサポートされています。The ++ and -- operators also support prefix notation (Prefix increment and decrement operators). 通常、x++ または x-- の結果は、操作の前の x の値になります。一方、++x または --x の結果は、操作後の x の値になります。Typically, the result of x++ or x-- is the value of x before the operation, whereas the result of ++x or --x is the value of x after the operation. どちらの場合も、x 自体の値は、操作の後で同じになります。In either case, x itself has the same value after the operation.

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.

new 式には、次の3つの形式があります。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. abstract class_typeにすることはできません。The 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内のいずれかの引数にコンパイル時の型が dynamic 場合、 object_creation_expressionは動的にバインドされ (動的バインディング)、次の規則は、コンパイル時の型 dynamicを持つargument_listの引数の実行時の型を使用して実行時に適用されます。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.

フォーム new T(A)object_creation_expressionのバインド時の処理。 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型の値です。つまり、システムの ValueType 型で定義されている T の既定値です。The result of the object_creation_expression is a value of type T, namely the default value for T as defined in The System.ValueType type.
  • それ以外の場合、Ttype_parameterA が存在しない場合は、次のようになります。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. 候補インスタンスコンストラクターのセットは、A (適用可能な関数メンバー) に対して適用できる、T で宣言されたすべてのアクセス可能なインスタンスコンストラクターで構成されます。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が動的にバインドされている場合でも、コンパイル時の型は引き続き Tます。Even if the object_creation_expression is dynamically bound, the compile-time type is still T.

フォーム new T(A)object_creation_expressionの実行時処理。 Tclass_typeまたはstruct_typeで、A は省略可能なargument_listで、次の手順で構成されています。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つの埋め込み Point インスタンスを割り当てる場合If 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[][,]. 式リストの各式は、型 intuintlong、または 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_initializers で見つかったすべてので構成されます。For a multidimensional array, i.e., one where the rank_specifier contains at least one comma, this set comprises all expressions found in nested array_initializers.

配列初期化子の詳細については、「配列初期化子」を参照してください。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. 各式を評価すると、次のいずれかの型への暗黙的な変換 (暗黙の変換) が実行されます: intuintlongulongFollowing evaluation of each expression, an implicit conversion (Implicit conversions) to one of the following types is performed: int, uint, long, ulong. 暗黙的な変換が存在する、この一覧の最初の型が選択されます。The first type in this list for which an implicit conversion exists is chosen. 式またはそれ以降の暗黙的な変換によって例外が発生した場合、それ以降の式は評価されず、それ以上の手順は実行されません。If evaluation of an expression or the subsequent implicit conversion causes an exception, then no further expressions are evaluated and no further steps are executed.
  • ディメンションの長さの計算値は、次のように検証されます。The computed values for the dimension lengths are validated as follows. 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][];

int[]型の100要素を含む1次元配列を作成します。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

最後の式では、intstring も暗黙的に他方に変換できないため、コンパイル時エラーが発生します。したがって、最適な共通型はありません。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 ')'
    ;

デリゲート作成式の引数には、メソッドグループ、匿名関数、またはコンパイル時の型 dynamic またはdelegate_typeのいずれかの値を指定する必要があります。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.

dynamicコンパイル時の型がある場合、 delegate_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.

フォーム new D(E)delegate_creation_expressionのバインド時の処理。 Ddelegate_typeで、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 が値の場合、EDと互換性がある (デリゲート宣言) 必要があります。また、結果は、Eと同じ呼び出しリストを参照する、D 型の新しく作成されたデリゲートへの参照になります。If E is a value, E must be compatible (Delegate declarations) with D, and the result is a reference to a newly created delegate of type D that refers to the same invocation list as E. EDと互換性がない場合は、コンパイル時にエラーが発生します。If E is not compatible with D, a compile-time error occurs.

フォーム new D(E)delegate_creation_expressionの実行時処理。 Ddelegate_typeで、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. 匿名型は、objectから直接継承する無名のクラス型です。An 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() { ... }
}

Txex対応する式の型です。where 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;

p1p2 が同じ匿名型であるため、最後の行の代入が許可されます。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. つまり、型 Tの場合、typeof(T) == typeof(T) は常に true になります。This means that for a type T, typeof(T) == typeof(T) is always true. dynamicにすることはできません。The 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_specifiers where a type_name contains type_argument_lists. 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_listに置き換えることにより、トークンのシーケンスをtype_nameに変換します。各type_argumentには 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]

intSystem.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 演算子は、チェックされていないコンテキストで含まれている式を評価します。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 の演算子またはステートメントでは囲まれていない非定数式 (実行時に評価される式) の場合、checked 評価のために外部要因 (コンパイラスイッチや実行環境の構成など) が呼び出されない限り、既定のオーバーフローチェックコンテキストは unchecked ます。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 または unchecked のコンテキストの影響を受けません。The 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 の定数式を評価するときにオーバーフローが発生すると、式は checked コンテキストで評価されるため、コンパイル時のエラーが報告されます。the 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.

checked 演算子と 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));
    }
}

F での checked の使用は Multiplyx * y の評価には影響しないため、既定のオーバーフローチェックコンテキストで x * y が評価されます。the use of checked in F does not affect the evaluation of x * y in Multiply, so x * y is evaluated in the default overflow checking context.

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つの浮動小数点数を乗算しても、明示的な checked コンストラクト内であってもオーバーフローで例外が発生することはありません。Similarly, multiplying two floats never results in an exception on overflow even within an explicitly checked construct. また、他の演算子は、既定でも明示的でも、チェックモードの影響を受けません。In addition, other operators are never affected by the mode of checking, whether default or explicit.

既定値の式Default value expressions

既定値の式は、型の既定値 (既定値) を取得するために使用されます。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). また、型が sbytebyteshortushortintuintlongulongcharfloatdoubledecimalbool、または任意の列挙型のいずれかの値型の場合、 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. 互換性の理由により、名前の名前の参照 (簡易名) が成功した場合、呼び出しが有効であるかどうかに関係なく、式はinvocation_expressionとして扱われます。 nameofFor 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_expressionstring型の定数式であり、実行時には効果がありません。A nameof_expression is a constant expression of type string, and has no effect at runtime. 具体的には、そのnamed_entityは評価されず、明確な代入分析 (単純式の一般的な規則) のために無視されます。Specifically, its named_entity is not evaluated, and is ignored for the purposes of definite assignment analysis (General rules for simple expressions). この値は、省略可能な最終type_argument_listの前のnamed_entityの最後の識別子で、次のように変換されます。Its value is the last identifier of the named_entity before the optional final type_argument_list, transformed in the following way:

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

これらは、識別子が等しいかどうかをテストするときに識別子に適用される変換と同じです。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.b 、null_conditional_operations ( null 条件要素アクセス)、?[0] (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 Pnull_conditional_expression E については、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 チェックに nullが見つからない場合に評価される式です。Conceptually, E0 is the expression that will be evaluated if none of the null checks represented by the ?s do find a null.

また、E内の最初のnull_conditional_operationsから先頭の ? を削除することによって得られる式を E1 します。Also, let E1 be the expression obtained by textually removing the leading ? from just the first of the null_conditional_operations in E. これにより、プライマリ式(?が1つだけの場合) または別の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 が何も分類されていない場合、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:

  • Estatement_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.ba.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.ba.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 の値がオペランド型の最小表現可能値 (int の場合は-2 ^ 31、longの場合は-2 ^ 63) である場合、x の算術否定はオペランド型では表現できません。If the value of x is the smallest representable value of the operand type (-2^31 for int or -2^63 for long), then the mathematical negation of x is not representable within the operand type. これが checked コンテキスト内で発生すると、System.OverflowException がスローされます。unchecked のコンテキスト内で発生した場合、結果はオペランドの値になり、オーバーフローは報告されません。If this occurs within a checked context, a System.OverflowException is thrown; if it occurs within an unchecked context, the result is the value of the operand and the overflow is not reported.

    否定演算子のオペランドが uint型である場合は、型 longに変換され、結果の型は longになります。If the operand of the negation operator is of type uint, it is converted to type long, and the type of the result is long. 例外として、int 値-2147483648 (-2 ^ 31) を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.Decimal型の単項マイナス演算子を使用することと同じです。Decimal 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 は、基になる型 Uの列挙 E 型の式であり、(E)(~(U)x)への変換が E のコンテキスト (checked および unchecked 演算子) の場合と同じように実行される点を除き、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.

前置インクリメントまたはデクリメント演算のオペランドがプロパティまたはインデクサーアクセスの場合、プロパティまたはインデクサーには、getset の両方のアクセサーが必要です。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. 定義済みの ++-- の演算子は、sbytebyteshortushortintuintlongulongcharfloatdoubledecimal、列挙型の各型に存在します。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:
    • インスタンス式 (xstaticでない場合) と 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.
    • xget アクセサーが呼び出されます。The get accessor of x is invoked.
    • 選択した演算子は、引数として get アクセサーによって返された値を使用して呼び出されます。The selected operator is invoked with the value returned by the get accessor as its argument.
    • xset アクセサーは、value 引数として演算子によって返された値を使用して呼び出されます。The set accessor of x is invoked with the value returned by the operator as its value argument.
    • 演算子によって返される値は、操作の結果になります。The value returned by the operator becomes the result of the operation.

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

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
    ;

フォーム (T)Ecast_expressionTEunary_expressionであり、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 (型 x-y をキャスト) として解釈するか、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 tokens (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 および isを除く任意のキーワード(キーワード) です。The sequence of tokens is correct grammar for a type, and the token immediately following the closing parentheses is the token "~", the token "!", the token "(", an identifier (Unicode character escape sequences), a literal (Literals), or any keyword (Keywords) except as and is.

上記の "正しい文法" という用語は、トークンのシーケンスが、特定の文章の作成に準拠している必要があることを意味します。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. たとえば、xy が識別子の場合、x.y が実際に型を表していない場合でも、x.y は型の正しい文法です。For 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 が識別子である場合、(x)y(x)(y)、および (x)(-y)cast_expressionであるにもかかわらず、(x)-y が型を識別する場合でも、この規則に従っています。From the disambiguation rule it follows that, if x and y are identifiers, (x)y, (x)(y), and (x)(-y) are cast_expressions, but (x)-y is not, even if x identifies a type. ただし、x が定義済みの型 (intなど) を識別するキーワードである場合、4つのすべての形式がcast_expressionます (このようなキーワードは、式自体ではない可能性があります)。However, if x is a keyword that identifies a predefined type (such as int), then all four forms are cast_expressions (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 (Iterators). 最も近い外側の非同期関数内では、次の場所では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のオペランドはタスクと呼ばれます。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 には、パラメーターを持たず、型パラメーターを持たない、アクセス可能なインスタンスメソッド GetResult がありますA 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 型と呼ばれます。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. Tvoid 以外の戻り値の型がある場合、 await_expressionT型の値として分類されます。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:

  • (t).GetAwaiter()を評価することによって、awaiter a を取得します。An awaiter a is obtained by evaluating the expression (t).GetAwaiter().
  • bool b は、式 (a).IsCompletedを評価することによって取得されます。A bool b is obtained by evaluating the expression (a).IsCompleted.
  • bfalse 場合、評価は a がインターフェイス System.Runtime.CompilerServices.ICriticalNotifyCompletion を実装しているかどうかによって異なります (簡潔にするために ICriticalNotifyCompletion として知られています)。If b is false then evaluation depends on whether a implements the interface System.Runtime.CompilerServices.ICriticalNotifyCompletion (hereafter known as ICriticalNotifyCompletion for brevity). このチェックは、バインド時に行われます。つまり、a がコンパイル時の型 dynamicであり、コンパイル時にそれ以外の場合は、実行時に実行されます。This check is done at binding time; i.e. at runtime if a has the compile time type dynamic, and at compile time otherwise. 再開デリゲート (反復子) を示す r を使用します。Let r denote the resumption delegate (Iterators):
    • aICriticalNotifyCompletionを実装していない場合は、式 (a as (INotifyCompletion)).OnCompleted(r) が評価されます。If a does not implement ICriticalNotifyCompletion, then the expression (a as (INotifyCompletion)).OnCompleted(r) is evaluated.
    • aICriticalNotifyCompletionを実装している場合、式 (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.
  • の直後 (btrueの場合)、または後で再開デリゲートを呼び出したとき (bfalseの場合)、式 (a).GetResult() が評価されます。Either immediately after (if b was true), or upon later invocation of the resumption delegate (if b was false), the expression (a).GetResult() is evaluated. 値が返された場合、その値はawait_expressionの結果になります。If it returns a value, that value is the result of the await_expression. それ以外の場合、結果は nothing です。Otherwise the result is nothing.

インターフェイスメソッド INotifyCompletion.OnCompleted および ICriticalNotifyCompletion.UnsafeOnCompleted の awaiter の実装では、デリゲート 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. すべての演算子は、xyの積を計算します。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. 結果値が小さすぎて decimal 形式で表現できない場合、結果は0になります。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.Decimal型の乗算演算子を使用することと同じです。Decimal 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. すべての演算子は、xyの商を計算します。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. 結果値が小さすぎて decimal 形式で表現できない場合、結果は0になります。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.Decimal型の除算演算子を使用することと同じです。Decimal 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. すべての演算子は、xy間の除算の剰余を計算します。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) * yによって生成される値です。The result of x % y is the value produced by x - (x / y) * y. 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 % y は例外をスローしません。In no case does x % y throw an exception where x / y would not throw an exception.

  • 浮動小数点の剰余:Floating-point remainder:

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

    次の表に、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 の結果であり、x - n * yとして計算されます。 n は、x / y以下の最大の整数です。z is the result of x % y and is computed as x - n * y, where n is the largest possible integer that is less than or equal to x / y. 余りを計算するこの方法は、整数オペランドに使用されるものと似ていますが、IEEE 754 定義とは異なります (nx / 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.Decimal型の剰余演算子を使用することと同じです。Decimal 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 が変換先の型で表すには大きすぎる場合、zx + yと同じ符号を持つ無限大です。If x + y is too large to represent in the destination type, z is an infinity with the same sign as x + y.

    Yy +0+0 横-0-0 +inf+inf -inf-inf NaNNaN
    Xx zz Xx Xx +inf+inf -inf-inf NaNNaN
    +0+0 Yy +0+0 +0+0 +inf+inf -inf-inf NaNNaN
    横-0-0 Yy +0+0 横-0-0 +inf+inf -inf-inf NaNNaN
    +inf+inf +inf+inf +inf+inf +inf+inf +inf+inf NaNNaN NaNNaN
    -inf-inf -inf-inf -inf-inf -inf-inf NaNNaN -inf-inf NaNNaN
    NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
  • 小数点の追加:Decimal 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.Decimal型の加算演算子を使用することと同じです。Decimal addition is equivalent to using the addition operator of type System.Decimal.

  • 列挙型の追加。Enumeration addition. すべての列挙型には、暗黙的に次の定義済みの演算子が用意されています。 E は列挙型であり、UEの基になる型です。Every enumeration type implicitly provides the following predefined operators, where E is the enum type, and U is the underlying type of E:

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

    実行時に、これらの演算子は (E)((U)x + (U)y)として正確に評価されます。At run-time these operators are evaluated exactly as (E)((U)x + (U)y).

  • 文字列の連結:String concatenation:

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

    これらのバイナリ + 演算子のオーバーロードは、文字列の連結を実行します。These overloads of the binary + operator perform string concatenation. 文字列連結のオペランドが null場合、空の文字列が置換されます。If an operand of string concatenation is null, an empty string is substituted. それ以外の場合、文字列以外の引数は、型 objectから継承された仮想 ToString メソッドを呼び出すことによって文字列形式に変換されます。Otherwise, any non-string argument is converted to its string representation by invoking the virtual ToString method inherited from type object. ToStringnullを返す場合、空の文字列が置換されます。If ToString returns null, an empty string is substituted.

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

    文字列連結演算子の結果は、左オペランドの文字と右オペランドの文字で構成される文字列です。 文字列連結演算子は、null 値を返しません。 結果の文字列を割り当てるために十分なメモリがない場合、System.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. すべての演算子は、xから y を減算します。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 が変換先の型で表すには大きすぎる場合、zx - yと同じ符号を持つ無限大です。If x - y is too large to represent in the destination type, z is an infinity with the same sign as x - y.

    Yy +0+0 横-0-0 +inf+inf -inf-inf NaNNaN
    Xx zz Xx Xx -inf-inf +inf+inf NaNNaN
    +0+0 -y-y +0+0 +0+0 -inf-inf +inf+inf NaNNaN
    横-0-0 -y-y 横-0-0 +0+0 -inf-inf +inf+inf NaNNaN
    +inf+inf +inf+inf +inf+inf +inf+inf NaNNaN +inf+inf NaNNaN
    -inf-inf -inf-inf -inf-inf -inf-inf -inf-inf NaNNaN NaNNaN
    NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN
  • 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.Decimal型の減算演算子を使用することと同じです。Decimal subtraction is equivalent to using the subtraction operator of type System.Decimal.

  • 列挙型の減算。Enumeration subtraction. すべての列挙型には、暗黙的に次の定義済みの演算子が用意されています。 E は列挙型であり、UEの基になる型です。Every enumeration type implicitly provides the following predefined operator, where E is the enum type, and U is the underlying type of E:

    U operator -(E x, E y);
    

    この演算子は (U)((U)x - (U)y)として正確に評価されます。This operator is evaluated exactly as (U)((U)x - (U)y). 言い換えると、演算子は xyの序数値の差を計算し、結果の型は列挙型の基になる型になります。In other words, the operator computes the difference between the ordinal values of x and y, and the type of the result is the underlying type of the enumeration.

    E operator -(E x, U y);
    

    この演算子は (E)((U)x - y)として正確に評価されます。This operator is evaluated exactly as (E)((U)x - y). つまり、演算子は列挙体の基になる型から値を減算し、列挙体の値を生成します。In other words, the operator subtracts a value from the underlying type of the enumeration, yielding a value of the enumeration.

  • デリゲートの削除。Delegate removal. すべてのデリゲート型は、次の定義済み演算子を暗黙的に提供します。 D はデリゲート型です。Every delegate type implicitly provides the following predefined operator, where D is the delegate type:

    D operator -(D x, D y);
    

    二項 - 演算子は、両方のオペランドがデリゲート型 Dである場合に、デリゲートの削除を実行します。The binary - operator performs delegate removal when both operands are of some delegate type D. オペランドのデリゲート型が異なる場合、バインド時エラーが発生します。If the operands have different delegate types, a binding-time error occurs. 最初のオペランドが null の場合は、演算結果は 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 << count または x >> 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.

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

    xuint または 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:

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

シフト操作ではオーバーフローが発生することはなく、checkedunchecked のコンテキストでも同じ結果が生成されます。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. たとえば、xint型の変数である場合、操作 unchecked((int)((uint)x >> y)) xの論理右シフトを実行します。For example, if x is a variable of type int, the operation unchecked((int)((uint)x >> y)) performs a logical shift right of x.

関係演算子と型検査演算子Relational and type-testing operators

==!=<><=>=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 op 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 xyに等しい場合は、それ以外の場合は falsetrue if x is equal to y, false otherwise
x != y true xyと等しくない場合は、それ以外の場合は falsetrue if x is not equal to y, false otherwise
x < y true xyより小さい場合は、それ以外の場合は falsetrue if x is less than y, false otherwise
x > y true xyより大きい場合は、それ以外の場合は falsetrue if x is greater than y, false otherwise
x <= y true xy以下の場合は、それ以外の場合は falsetrue if x is less than or equal to y, false otherwise
x >= y true xy以上の場合は、それ以外の場合は 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つの整数オペランドの数値を比較し、特定のリレーションシップが true または falseかどうかを示す bool 値を返します。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. たとえば、xy のいずれかが NaN の場合、x < yfalseますが、!(x >= y)trueです。For 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
    

    ここで minmax は、指定された浮動小数点形式で表すことができる最小値と最大値の正の有限値です。where min and max are the smallest and largest positive finite values that can be represented in the given floating-point format. この順序の主な影響は次のとおりです。Notable effects of this ordering are:

    • 負のゼロと正のゼロは等しいと見なされます。Negative and positive zeros are considered equal.
    • 負の無限大は、他のすべての値よりも小さいと見なされますが、負の負の無限大と同じです。A negative infinity is considered less than all other values, but equal to another negative infinity.
    • 正の無限大は、他のすべての値よりも大きいと見なされますが、もう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進オペランドの数値を比較し、特定のリレーションシップが true または falseかどうかを示す bool 値を返します。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.Decimal型の対応する関係演算子または等値演算子を使用することと同じです。Each 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);

xy の両方が true である場合、または xy の両方が false場合は、== の結果が true ます。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.

xy の両方が true である場合、または xy の両方が false場合は、!= の結果が 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 は、基になる型 UE 列挙型の式であり、比較演算子の1つである op((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またはリテラル nullであると認識される型の値です。Both operands are a value of a type known to be a reference_type or the literal null. さらに、明示的な参照変換 (明示的な参照変換) は、いずれかのオペランドの型からもう一方のオペランドの型に存在します。Furthermore, an explicit reference conversion (Explicit reference conversions) exists from the type of either operand to the type of the other operand.
  • 1つのオペランドは T 型の値で、Ttype_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. たとえば、オペランドのバインド時の型が A および Bの2つのクラス型であり、どちらも AB も派生していない場合は、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 が値型を表している場合でも許可されます。 T が値型の場合、結果は単純に false されるように定義されます。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. 2つのオペランドの型が stringの場合、定義済みの文字列等値演算子 (文字列等値演算子) が選択されているので、最初の比較で True が出力されます。The first comparison outputs True because the predefined string equality operator (String equality operators) is selected when both operands are of type string. 一方または両方のオペランドが object型の場合、定義済みの参照型等値演算子が選択されているので、残りのすべての出力 False になります。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);
    }
}

キャストによって、ボックス化された int 値の2つの異なるインスタンスへの参照が作成されるため、False 出力されます。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);

次のいずれかに該当する場合、2つの string 値は等しいと見なされます。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_expressions またはlambda_expressionの評価から生成された呼び出しリストのエントリは、同じにすることができます (ただし、必須ではありません)。Invocation list entries produced from evaluation of semantically identical anonymous_method_expressions or lambda_expressions with the same (possibly empty) set of captured outer variable instances are permitted (but not required) to be equal.

等値演算子と nullEquality operators and null

== 演算子と != 演算子では、1つのオペランドを null 許容型の値にすることができます。また、操作に対して定義済みまたはユーザー定義の演算子 (unlifted またはリフト形式) が存在しない場合でも、一方のオペランドは null リテラルになります。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 許容型の式で、演算子のオーバーロード解決 (二項演算子のオーバーロードの解決) が適用可能な演算子を見つけることができない場合、結果は xHasValue プロパティから計算されます。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 は型であり、参照変換、ボックス化変換、またはボックス化解除変換によって ET 型に正常に変換できるかどうかを示すブール値です。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 許容型で、E の値が null の場合、結果は false になります。If E is a method group or the null literal, of if the type of E is a reference type or a nullable type and the value of E is null, the result is false.
  • それ以外の場合は、次のように E の動的な型を D します。Otherwise, let D represent the dynamic type of E as follows:
    • E の型が参照型の場合、DEによってインスタンス参照の実行時の型になります。If the type of E is a reference type, D is the run-time type of the instance reference by E.
    • E の型が null 許容型である場合、D はその null 許容型の基になる型です。If the type of E is a nullable type, D is the underlying type of that nullable type.
    • E の型が null 非許容の値型の場合、DEの型になります。If the type of E is a non-nullable value type, D is the type of E.
  • 操作の結果は DT によって次のように異なります。The result of the operation depends on D and T as follows:
    • T が参照型の場合、結果は true になります。これは、DT が同じ型である場合、D が参照型である場合、および D から T 存在する暗黙的な参照変換である場合、または D から D へのボックス変換が存在する場合に発生します。If T is a reference type, the result is true if D and T are the same type, if D is a reference type and an implicit reference conversion from D to T exists, or if D is a value type and a boxing conversion from D to T exists.
    • T が null 許容型である場合、DTの基になる型である場合、結果は true になります。If T is a nullable type, the result is true if D is the underlying type of T.
    • T が null 非許容の値型である場合、DT が同じ型である場合、結果は true になります。If T is a non-nullable value type, the result is true if D and T are the same type.
    • それ以外の場合、結果は false になります。Otherwise, the result is false.

ユーザー定義の変換は、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 T によって同じ結果が生成されます。If 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. コンパイラは、上記の拡張によって暗黙的に指定された2つの動的な型チェックではなく、最大で1つの動的な型チェックを実行するように E as T を最適化することを想定できます。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場合、cast 演算子とは異なり、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 
    }
}

G の型パラメーター T は、クラスの制約があるため、参照型であることがわかっています。the type parameter T of G is known to be a reference type, because it has the class constraint. H の型パラメーター U がではありません。したがって、H での as 演算子の使用は許可されていません。The type parameter U of H is not however; hence the use of the as operator in H is disallowed.

論理演算子Logical operators

&^、および | の各演算子は、論理演算子と呼ばれます。The &, ^, and | operators are called the logical operators.

and_expression
    : equality_expression
    | and_expression '&' equality_expression
    ;

exclusive_or_expression
    : and_expression
    | exclusive_or_expression '^' and_expression
    ;

inclusive_or_expression
    : exclusive_or_expression
    | inclusive_or_expression '|' exclusive_or_expression
    ;

論理演算子のオペランドに 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つのオペランドのビットごとの論理 AND を計算します。 | OR 演算子は、2つのオペランドのビットごとの論理和を計算し、^ 演算子は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を評価した結果 xy は、基になる型 UE 列挙型の式であり、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 または ytrueの場合、x | y の結果は true です。The result of x | y is true if either x or y is true. それ以外の場合、結果は false です。Otherwise, the result is false.

xtrueyfalseである場合、または xfalseytrue場合、x ^ 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つの値、truefalse、および 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);

次の表に、truefalse、および 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
    ;

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

  • 操作 x && y は操作 x & yに対応しますが、xfalseされていない場合にのみ y が評価される点が異なります。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に対応しますが、xtrueされていない場合にのみ y が評価される点が異なります。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 && yx ? 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. 次に、xtrue場合、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 || yx ? 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. 次に、xtrue場合、操作の結果は 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. 言い換えると、演算子は T型の2つのオペランドの論理 AND または論理 OR を計算する必要があり、型 Tの結果を返す必要があります。In other words, the operator must compute the logical AND or the logical OR of two operands of type T, and must return a result of type T.
  • Toperator trueoperator 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 && yT.false(x) ? x : T.&(x, y)として評価されます。 T.false(x)Tで宣言された operator false の呼び出しで、T.&(x, y) は選択した operator &の呼び出しです。The operation x && y is evaluated as T.false(x) ? x : T.&(x, y), where T.false(x) is an invocation of the operator false declared in T, and T.&(x, y) is an invocation of the selected operator &. つまり、x は最初に評価され、結果に対して operator false が呼び出され、x が確実に false であるかどうかが判断されます。In other words, x is first evaluated and operator false is invoked on the result to determine if x is definitely false. x が確実に false の場合、操作の結果は、以前に xに対して計算された値になります。Then, if x is definitely false, the result of the operation is the value previously computed for x. それ以外の場合、y が評価され、選択した 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 || yT.true(x) ? x : T.|(x, y)として評価されます。 T.true(x)Tで宣言された operator true の呼び出しで、T.|(x,y) は選択した operator|の呼び出しです。The operation x || y is evaluated as T.true(x) ? x : T.|(x, y), where T.true(x) is an invocation of the operator true declared in T, and T.|(x,y) is an invocation of the selected operator|. つまり、x が最初に評価され、結果に対して operator true が呼び出され、x が確実に真であるかどうかが判断されます。In other words, x is first evaluated and operator true is invoked on the result to determine if x is definitely true. x が確実に true の場合、操作の結果は、以前に xに対して計算された値になります。Then, if x is definitely true, the result of the operation is the value previously computed for x. それ以外の場合、y が評価され、選択した 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 trueoperator 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
    ;

a ?? b 形式の null 結合式では、a null 許容型または参照型である必要があります。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. 操作は、a が null の場合にのみ b を評価します。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 の型は A0A、または Bです。ここで Aa の型 (a に型がある場合)、B が null 許容型である場合は b の基になる型であり、それ以外の場合は b になります。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 でない場合、aA0型にラップ解除され、結果になります。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.
  • それ以外の場合、bB 型があり、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 でない場合、aA0 型にラップ解除され (A 存在し、null 値が許容される場合)、型 Bに変換され、これが結果になります。If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. それ以外の場合、b が評価され、結果になります。Otherwise, b is evaluated and becomes the result.
  • それ以外の場合、ab に互換性がなく、コンパイル時にエラーが発生します。Otherwise, a and b are incompatible, and a compile-time error occurs.

条件演算子Conditional operator

?: 演算子は、条件演算子と呼ばれます。The ?: operator is called the conditional operator. これは、三項演算子とも呼ばれます。It is at times also called the ternary operator.

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

b ? x : y フォームの条件式は、最初に条件 bを評価します。A conditional expression of the form b ? x : y first evaluates the condition b. 次に、btrue場合、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. 条件式では、xyの両方が評価されることはありません。A 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 型がある場合は YIf 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.
  • xy の1つだけが型を持ち、xyの両方がその型に暗黙的に変換可能な場合は、それが条件式の型になります。If only one of x and y has a type, and both x and y, of are implicitly convertible to that type, then that is the type of the conditional expression.
  • それ以外の場合は、式の型を特定できないため、コンパイル時エラーが発生します。Otherwise, no expression type can be determined, and a compile-time error occurs.

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

  • まず、b が評価され、bbool 値が決定されます。First, b is evaluated, and the bool value of b is determined:
    • b の型から bool への暗黙的な変換が存在する場合、この暗黙の変換は bool 値を生成するために実行されます。If an implicit conversion from the type of b to bool exists, then this implicit conversion is performed to produce a bool value.
    • それ以外の場合、b の型によって定義された operator true は、bool 値を生成するために呼び出されます。Otherwise, the operator true defined by the type of b is invoked to produce a bool value.
  • 上記の手順で生成された bool 値が true場合、x が評価され、条件式の型に変換され、これが条件式の結果になります。If the bool value produced by the step above is true, then x is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression.
  • それ以外の場合、y が評価され、条件式の型に変換されます。これは条件式の結果になります。Otherwise, y is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression.

匿名関数式Anonymous function expressions

匿名関数は、"インライン" メソッド定義を表す式です。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_expressions とanonymous_method_expressions です。For historical reasons there are two syntactic flavors of anonymous functions, namely lambda_expressions and anonymous_method_expressions. ほとんどの場合、 lambda_expressionanonymous_method_expressionより簡潔で表現力が豊かで、下位互換性のために言語に残されています。For almost all purposes, lambda_expressions are more concise and expressive than anonymous_method_expressions, 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 修飾子を持つ匿名関数は、非同期関数であり、「反復子」で説明されている規則に従います。An anonymous function with the async modifier is an async function and follows the rules described in Iterators.

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

  • anonymous_method_expressions を使用すると、パラメーターリストを完全に省略でき、値パラメーターのリストのデリゲート型に convertibility が生成されます。anonymous_method_expressions permit the parameter list to be omitted entirely, yielding convertibility to delegate types of any list of value parameters.
  • lambda_expressions では、パラメーターの型を省略し、推論することができますが、 anonymous_method_expressions ではパラメーターの型を明示的に指定する必要があります。lambda_expressions permit parameter types to be omitted and inferred whereas anonymous_method_expressions require parameter types to be explicitly stated.
  • Lambda_expressionの本体は、式またはステートメントブロックにすることができます。一方、 anonymous_method_expressionの本体は、ステートメントブロックである必要があります。The body of a lambda_expression can be an expression or a statement block whereas the body of an anonymous_method_expression must be a statement block.
  • 互換性のある式ツリー型 (式ツリー型) に変換できるのはlambda_expressions だけです。Only lambda_expressions 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の最初の呼び出しでは、匿名関数 d => d. UnitCountFunc<Detail,int>Func<Detail,double>の両方と互換性があるため、両方の Sum メソッドが適用されます。In the first invocation of orderDetails.Sum, both Sum methods are applicable because the anonymous function d => d. UnitCount is compatible with both Func<Detail,int> and Func<Detail,double>. ただし、オーバーロードの解決では、最初の Sum メソッドが選択されます。これは、Func<Detail,int> への変換が Func<Detail,double>への変換よりも優れているためです。However, overload resolution picks the first Sum method because the conversion to Func<Detail,int> is better than the conversion to Func<Detail,double>.

orderDetails.Sumの2番目の呼び出しでは、匿名関数 d => d.UnitPrice * d.UnitCountdouble型の値を生成するため、2番目の Sum メソッドのみが適用されます。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 は匿名関数によってキャプチャされ、F から返されたデリゲートがガベージコレクションの対象になるまで、x の有効期間が少なくとも拡張されます (これは、プログラムの終わりまで発生しません)。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 の宣言をループの外側に移動すると、xの1つのインスタンスが生成されます。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 は、直接的に、またはデリゲート作成式 new D(F)の実行を通じて、デリゲート型 D または式ツリー E型に常に変換される必要があります。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個以上の fromletwherejoin または 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 句または 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. 最後に、1つのクエリの結果を後続のクエリでジェネレーターとして扱うことによって、into 句を使用してクエリを "スプライス" できます。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. 具体的には、fromwherejoinonequalsintoletorderbyascendingdescendingselectgroupbyです。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). 具体的には、クエリ式は、WhereSelectSelectManyJoinGroupJoinOrderByOrderByDescendingThenByThenByDescendingGroupByCastという名前のメソッドの呼び出しに変換されます。これらのメソッドには、クエリ式パターンで説明されているように、特定のシグネチャと結果型が必要です。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

範囲変数の型を明示的に指定する fromA from clause that explicitly specifies a range variable type

from T x in e

はに変換されます。is translated into

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

範囲変数の型を明示的に指定する joinA 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. 上記の例では、customersArrayList型である場合、これが当てはまります。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 句の後に select 句を指定したクエリ式A 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 句の後に select 句以外のものが続くクエリ式:A 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 } )
...

let 句を含むクエリ式A 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 } )
...

where 句を含むクエリ式A query expression with a where clause

from x in e
where f
...

はに変換されます。is translated into

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

into の後に select 句が指定されていない join 句を含むクエリ式A 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 )

into の後に select 句以外のものが指定されていない join 句を含むクエリ式A 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 })
...

into の後に select 句が続く join 句を含むクエリ式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 )

into の後に select 句以外のものが含まれている join 句を含むクエリ式A 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 })
...

orderby 句を含むクエリ式A 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.

次の変換では、letwherejoin、または 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 })

xy、および 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 of the following steps:

  • x が変数として分類される場合は、次のようになります。If x is classified as a variable:
    • 変数を生成するために x が評価されます。x is evaluated to produce the variable.
    • y が評価され、必要に応じて、暗黙的な変換 (暗黙の変換) によって x の型に変換されます。y is evaluated and, if required, converted to the type of x through an implicit conversion (Implicit conversions).
    • x によって指定された変数がreference_typeの配列要素である場合は、y に対して計算された値が、x が要素である配列インスタンスと互換性があることを確認するために、実行時チェックが実行されます。If the variable given by x is an array element of a reference_type, a run-time check is performed to ensure that the value computed for y is compatible with the array instance of which x is an element. ynull場合、または y によって参照されるインスタンスの実際の型から xを含む配列インスタンスの実際の要素型への暗黙の参照変換 (暗黙的な参照変換) が存在する場合、チェックは成功します。The check succeeds if y is null, or if an implicit reference conversion (Implicit reference conversions) exists from the actual type of the instance referenced by y to the actual element type of the array instance containing x. それ以外の場合は、System.ArrayTypeMismatchException がスローされます。Otherwise, a System.ArrayTypeMismatchException is thrown.
    • y の評価および変換の結果として得られる値は、xの評価によって指定された場所に格納されます。The value resulting from the evaluation and conversion of y is stored into the location given by the evaluation of x.
  • x がプロパティまたはインデクサーアクセスとして分類される場合は、次のようになります。If x is classified as a property or indexer access:
    • インスタンス式 (xstaticでない場合) と x に関連付けられている引数リスト (x がインデクサーアクセスの場合) が評価され、その結果が後続の set アクセサー呼び出しで使用されます。The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent set accessor invocation.
    • y が評価され、必要に応じて、暗黙的な変換 (暗黙の変換) によって x の型に変換されます。y is evaluated and, if required, converted to the type of x through an implicit conversion (Implicit conversions).
    • xset アクセサーは、value 引数として y に対して計算された値を使用して呼び出されます。The set accessor of x is invoked with the value computed for y as its value argument.

配列のクロス分散規則 (配列の共変性) では、配列型の値を A[] 配列型のインスタンスへの参照にすることが許可されています。これは、B から Aへの暗黙的な参照変換が存在する場合に B[]です。The array co-variance rules (Array covariance) permit a value of an array t