変換Conversions

変換を使用すると、式を特定の型として扱うことができます。A conversion enables an expression to be treated as being of a particular type. 変換によって、指定された型の式が別の型として処理されるか、型のない式が型を取得する可能性があります。A conversion may cause an expression of a given type to be treated as having a different type, or it may cause an expression without a type to get a type. 変換は暗黙的または明示的に行うことができます。これにより、明示的なキャストが必要かどうかが決まります。Conversions can be implicit or explicit, and this determines whether an explicit cast is required. たとえば、型 int から型 long への変換は暗黙的に行われるため、型 int の式は暗黙的に型 longとして扱うことができます。For instance, the conversion from type int to type long is implicit, so expressions of type int can implicitly be treated as type long. long から int型への逆の変換は明示的であるため、明示的なキャストが必要です。The opposite conversion, from type long to type int, is explicit and so an explicit cast is required.

int a = 123;
long b = a;         // implicit conversion from int to long
int c = (int) b;    // explicit conversion from long to int

一部の変換は、言語によって定義されます。Some conversions are defined by the language. プログラムでは、独自の変換 (ユーザー定義の変換) を定義することもできます。Programs may also define their own conversions (User-defined conversions).

暗黙の変換Implicit conversions

次の変換は、暗黙的な変換として分類されます。The following conversions are classified as implicit conversions:

  • Id 変換Identity conversions
  • 暗黙の数値変換Implicit numeric conversions
  • 暗黙的な列挙変換Implicit enumeration conversions
  • 暗黙的な挿入文字列の変換Implicit interpolated string conversions
  • 暗黙の null 許容型変換Implicit nullable conversions
  • Null リテラル変換Null literal conversions
  • 暗黙の参照変換Implicit reference conversions
  • ボックス化変換Boxing conversions
  • 暗黙の動的変換Implicit dynamic conversions
  • 暗黙の定数式の変換Implicit constant expression conversions
  • ユーザー定義の暗黙的な変換User-defined implicit conversions
  • 匿名関数の変換Anonymous function conversions
  • メソッドグループの変換Method group conversions

暗黙の型変換は、関数メンバー呼び出し (動的なオーバーロード解決のコンパイル時のチェック)、キャスト式 (キャスト式)、代入 (代入演算子) など、さまざまな状況で発生する可能性があります。Implicit conversions can occur in a variety of situations, including function member invocations (Compile-time checking of dynamic overload resolution), cast expressions (Cast expressions), and assignments (Assignment operators).

定義済みの暗黙的な変換は常に成功し、例外がスローされることはありません。The pre-defined implicit conversions always succeed and never cause exceptions to be thrown. 適切に設計されたユーザー定義の暗黙的な変換でも、これらの特性が示されます。Properly designed user-defined implicit conversions should exhibit these characteristics as well.

変換のために、型 objectdynamic は同等と見なされます。For the purposes of conversion, the types object and dynamic are considered equivalent.

ただし、動的変換 (暗黙の動的変換と明示的な動的変換) は dynamic 型の式 (動的型) にのみ適用されます。However, dynamic conversions (Implicit dynamic conversions and Explicit dynamic conversions) apply only to expressions of type dynamic (The dynamic type).

Id 変換Identity conversion

Id 変換は、任意の型から同じ型に変換します。An identity conversion converts from any type to the same type. この変換は、既に必要な型を持つエンティティをその型に変換できるようにするために存在します。This conversion exists such that an entity that already has a required type can be said to be convertible to that type.

  • objectdynamic は同等と見なされるため、objectdynamic間の id 変換と、dynamic のすべての出現箇所を objectに置き換える場合の構築された型の間の id 変換があります。Because object and dynamic are considered equivalent there is an identity conversion between object and dynamic, and between constructed types that are the same when replacing all occurrences of dynamic with object.

暗黙の数値変換Implicit numeric conversions

暗黙的な数値変換は次のとおりです。The implicit numeric conversions are:

  • sbyte から shortintlongfloatdoubledecimalになります。From sbyte to short, int, long, float, double, or decimal.
  • byte から shortushortintuintlongulongfloatdoubledecimalになります。From byte to short, ushort, int, uint, long, ulong, float, double, or decimal.
  • short から intlongfloatdoubledecimalになります。From short to int, long, float, double, or decimal.
  • ushort から intuintlongulongfloatdoubledecimalになります。From ushort to int, uint, long, ulong, float, double, or decimal.
  • int から longfloatdouble、または decimalになります。From int to long, float, double, or decimal.
  • uint から longulongfloatdoubledecimalになります。From uint to long, ulong, float, double, or decimal.
  • long から floatdouble、または decimalFrom long to float, double, or decimal.
  • ulong から floatdouble、または decimalFrom ulong to float, double, or decimal.
  • char から ushortintuintlongulongfloatdoubledecimalになります。From char to ushort, int, uint, long, ulong, float, double, or decimal.
  • float から doubleFrom float to double.

intuintlong、または ulong から float への変換または long への変換は、精度の低下を招く可能性がありますが、マグニチュードが失われることはありません。Conversions from int, uint, long, or ulong to float and from long or ulong to double may cause a loss of precision, but will never cause a loss of magnitude. その他の暗黙的な数値変換では、情報が失われることはありません。The other implicit numeric conversions never lose any information.

char 型への暗黙的な変換は行われないため、他の整数型の値は char 型に自動的に変換されません。There are no implicit conversions to the char type, so values of the other integral types do not automatically convert to the char type.

暗黙的な列挙変換Implicit enumeration conversions

暗黙的な列挙型変換では、 decimal_integer_literal 0 を任意のenum_typeに変換し、基になる型がenum_typeであるすべてのnullable_typeに変換できます。An implicit enumeration conversion permits the decimal_integer_literal 0 to be converted to any enum_type and to any nullable_type whose underlying type is an enum_type. 後者の場合、変換は、基になるenum_typeに変換し、結果をラップすることによって評価されます (null 許容型)。In the latter case the conversion is evaluated by converting to the underlying enum_type and wrapping the result (Nullable types).

暗黙的な挿入文字列の変換Implicit interpolated string conversions

暗黙的な補間文字列変換は、 interpolated_string_expression (挿入文字列) を System.IFormattable または System.FormattableString (System.IFormattableを実装) に変換することを許可します。An implicit interpolated string conversion permits an interpolated_string_expression (Interpolated strings) to be converted to System.IFormattable or System.FormattableString (which implements System.IFormattable).

この変換が適用された場合、文字列値は挿入文字列からは構成されません。When this conversion is applied a string value is not composed from the interpolated string. 代わりに、「挿入文字列」で詳しく説明されているように、System.FormattableString のインスタンスが作成されます。Instead an instance of System.FormattableString is created, as further described in Interpolated strings.

暗黙の null 許容型変換Implicit nullable conversions

Null 非許容の値型に対して動作する定義済みの暗黙的な変換は、これらの型の null 許容形式でも使用できます。Predefined implicit conversions that operate on non-nullable value types can also be used with nullable forms of those types. Null 非許容の値型から null 非許容の値 T型に変換する、定義済みの暗黙的な id および数値変換については、次の暗黙的な null 許容の変換が存在します。 SFor each of the predefined implicit identity and numeric conversions that convert from a non-nullable value type S to a non-nullable value type T, the following implicit nullable conversions exist:

  • S? から T?への暗黙的な変換です。An implicit conversion from S? to T?.
  • S から T?への暗黙的な変換です。An implicit conversion from S to T?.

S から T への基になる変換に基づく null 許容型の暗黙的な変換の評価は次のように行われます。Evaluation of an implicit nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Null 許容型変換が S? から T?の場合は、次のようになります。If the nullable conversion is from S? to T?:

    • ソース値が null (HasValue プロパティが false) の場合、結果は T?型の null 値になります。If the source value is null (HasValue property is false), the result is the null value of type T?.
    • それ以外の場合、変換は S? から Sへのラップ解除として評価された後、S から Tへの基になる変換と、T から T?へのラップ (Null 許容型) が行われます。Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping (Nullable types) from T to T?.
  • Null 許容型変換が S から T?に対して行われる場合、変換は S から T の基になる変換として評価され、その後、T から T?へのラップが行われます。If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.

Null リテラル変換Null literal conversions

null リテラルから null 許容型への暗黙的な変換が存在します。An implicit conversion exists from the null literal to any nullable type. この変換では、null 許容型の null 値 (null許容型) が生成されます。This conversion produces the null value (Nullable types) of the given nullable type.

暗黙の参照変換Implicit reference conversions

暗黙の参照変換は次のとおりです。The implicit reference conversions are:

  • 任意のreference_typeから object して dynamicします。From any reference_type to object and dynamic.
  • 任意のclass_type S から任意のclass_type Tへの S は、Tから派生しています。From any class_type S to any class_type T, provided S is derived from T.
  • 任意のclass_type S から、STを実装しているinterface_type TFrom any class_type S to any interface_type T, provided S implements T.
  • 任意のinterface_type S から任意のinterface_type Tへの S は、Tから派生しています。From any interface_type S to any interface_type T, provided S is derived from T.
  • 要素型が Tarray_type S から、次のすべてが満たされていれば、要素型が TEarray_typeSE ます。From an array_type S with an element type SE to an array_type T with an element type TE, provided all of the following are true:
    • ST は要素の型のみが異なります。S and T differ only in element type. 言い換えると、ST の次元数が同じになります。In other words, S and T have the same number of dimensions.
    • SETE は両方ともreference_typeです。Both SE and TE are reference_types.
    • SE から TEへの暗黙的な参照変換が存在します。An implicit reference conversion exists from SE to TE.
  • 任意のarray_typeから System.Array とそれが実装するインターフェイス。From any array_type to System.Array and the interfaces it implements.
  • S から Tへの暗黙的な id または参照の変換がある場合は、1次元配列型から System.Collections.Generic.IList<T> とその基本インターフェイスを S[] します。From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, provided that there is an implicit identity or reference conversion from S to T.
  • 任意のdelegate_typeから System.Delegate とそれが実装するインターフェイス。From any delegate_type to System.Delegate and the interfaces it implements.
  • Null リテラルから任意のreference_typeにします。From the null literal to any reference_type.
  • Reference_type T0 への暗黙的な id または参照の変換がある場合は、任意のreference_typeからreference_type TT0 には Tへの id 変換が含まれています。From any reference_type to a reference_type T if it has an implicit identity or reference conversion to a reference_type T0 and T0 has an identity conversion to T.
  • インターフェイスまたはデリゲート型への暗黙的な id または参照の変換がある場合は、任意のreference_typeからインターフェイスまたはデリゲート型に TT0 および T0Tへの分散変換可能 (変位変換) になります。From any reference_type to an interface or delegate type T if it has an implicit identity or reference conversion to an interface or delegate type T0 and T0 is variance-convertible (Variance conversion) to T.
  • 参照型として認識されている型パラメーターを使用する暗黙的な変換。Implicit conversions involving type parameters that are known to be reference types. 型パラメーターを使用する暗黙的な変換の詳細については、「型パラメーターに関連する暗黙的な変換」を参照してください。See Implicit conversions involving type parameters for more details on implicit conversions involving type parameters.

暗黙の参照変換とはreference_typeの間の変換であり、常に成功することが証明されるため、実行時のチェックは必要ありません。The implicit reference conversions are those conversions between reference_types that can be proven to always succeed, and therefore require no checks at run-time.

暗黙的または明示的な参照変換では、変換するオブジェクトの参照 id は変更されません。Reference conversions, implicit or explicit, never change the referential identity of the object being converted. つまり、参照変換によって参照の型が変更されても、参照先のオブジェクトの型または値が変更されることはありません。In other words, while a reference conversion may change the type of the reference, it never changes the type or value of the object being referred to.

ボックス化変換Boxing conversions

ボックス化変換は、 value_typeを参照型に暗黙的に変換することを許可します。A boxing conversion permits a value_type to be implicitly converted to a reference type. ボックス化変換は、すべてのnon_nullable_value_typeから objectdynamicに、 interface_typeによって実装されている任意のnon_nullable_value_typeに対して System.ValueType およびに対して行われます。A boxing conversion exists from any non_nullable_value_type to object and dynamic, to System.ValueType and to any interface_type implemented by the non_nullable_value_type. さらに、 enum_typeSystem.Enum型に変換できます。Furthermore an enum_type can be converted to the type System.Enum.

基になるnon_nullable_value_typeから参照型へのボックス変換が存在する場合にのみ、 nullable_typeから参照型へのボックス変換が存在します。A boxing conversion exists from a nullable_type to a reference type, if and only if a boxing conversion exists from the underlying non_nullable_value_type to the reference type.

値型には、インターフェイス型へのボックス変換が I0 ある場合は I インターフェイス型へのボックス変換があり、I0 には Iへの id 変換が含まれています。A value type has a boxing conversion to an interface type I if it has a boxing conversion to an interface type I0 and I0 has an identity conversion to I.

値型には、インターフェイス型またはデリゲート I0 型へのボックス変換がある場合は I インターフェイス型へのボックス変換があり、I0Iへの変位変換 (変位変換) があります。A value type has a boxing conversion to an interface type I if it has a boxing conversion to an interface or delegate type I0 and I0 is variance-convertible (Variance conversion) to I.

Non_nullable_value_typeの値のボックス化では、オブジェクトインスタンスを割り当て、そのインスタンスにvalue_type値をコピーします。Boxing a value of a non_nullable_value_type consists of allocating an object instance and copying the value_type value into that instance. 構造体は、すべての構造体 (継承) の基本クラスであるため System.ValueType型にボックス化できます。A struct can be boxed to the type System.ValueType, since that is a base class for all structs (Inheritance).

Nullable_typeの値をボックス化すると、次のように処理されるようになります。Boxing a value of a nullable_type proceeds as follows:

  • ソース値が null (HasValue プロパティが false) の場合、結果はターゲット型の null 参照になります。If the source value is null (HasValue property is false), the result is a null reference of the target type.
  • それ以外の場合、結果は、ソース値のラップ解除とボックス化によって生成されるボックス化された T への参照になります。Otherwise, the result is a reference to a boxed T produced by unwrapping and boxing the source value.

ボックス化変換の詳細については、「ボックス化変換」を参照してください。Boxing conversions are described further in Boxing conversions.

暗黙の動的変換Implicit dynamic conversions

dynamic 型の式から T任意の型への暗黙の動的変換が存在します。An implicit dynamic conversion exists from an expression of type dynamic to any type T. 変換は動的にバインドされます (動的バインド)。つまり、Tする式の実行時の型から、実行時に暗黙的な変換がシークされます。The conversion is dynamically bound (Dynamic binding), which means that an implicit conversion will be sought at run-time from the run-time type of the expression to T. 変換が見つからない場合は、実行時例外がスローされます。If no conversion is found, a run-time exception is thrown.

この暗黙的な変換は、暗黙的な変換では例外が発生しないという暗黙の変換の開始時のアドバイスには違反していることに注意してください。Note that this implicit conversion seemingly violates the advice in the beginning of Implicit conversions that an implicit conversion should never cause an exception. ただし、これは変換自体ではなく、例外を発生させる変換の検索です。However it is not the conversion itself, but the finding of the conversion that causes the exception. 実行時例外のリスクは、動的バインドの使用に固有のものです。The risk of run-time exceptions is inherent in the use of dynamic binding. 変換の動的バインドが望ましくない場合は、式を最初に objectに変換し、次に目的の型に変換できます。If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

暗黙の動的変換の例を次に示します。The following example illustrates implicit dynamic conversions:

object o  = "object"
dynamic d = "dynamic";

string s1 = o; // Fails at compile-time -- no conversion exists
string s2 = d; // Compiles and succeeds at run-time
int i     = d; // Compiles but fails at run-time -- no conversion exists

s2i の割り当てには、暗黙的な動的変換が使用されます。この場合、操作のバインドは実行時まで中断されます。The assignments to s2 and i both employ implicit dynamic conversions, where the binding of the operations is suspended until run-time. 実行時には、暗黙的な変換は、d -- string の実行時の型から対象の型にシークされます。At run-time, implicit conversions are sought from the run-time type of d -- string -- to the target type. string への変換は見つかりましたが、intはありません。A conversion is found to string but not to int.

暗黙の定数式の変換Implicit constant expression conversions

暗黙の定数式の変換では、次の変換が許可されます。An implicit constant expression conversion permits the following conversions:

  • int 型のconstant_expression (定数式) は、 short の値が変換先の型の範囲内にある場合に、型 sbytebyteushortuintulong、または constant_expression に変換できます。A constant_expression (Constant expressions) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant_expression is within the range of the destination type.
  • Constant_expressionの値が負でない場合は、型 longconstant_expressionulong型に変換できます。A constant_expression of type long can be converted to type ulong, provided the value of the constant_expression is not negative.

型パラメーターを含む暗黙の型変換Implicit conversions involving type parameters

指定された型パラメーター Tには、次の暗黙的な変換が存在します。The following implicit conversions exist for a given type parameter T:

  • T から、有効な基本クラス CT から Cの任意の基底クラス、T によって実装されている任意のインターフェイスに Cます。From T to its effective base class C, from T to any base class of C, and from T to any interface implemented by C. 実行時に T が値型の場合、変換はボックス化変換として実行されます。At run-time, if T is a value type, the conversion is executed as a boxing conversion. それ以外の場合、暗黙的な参照変換または id 変換として変換が実行されます。Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • T から、Tの有効なインターフェイスセット内の I インターフェイス型と、T から Iの任意の基本インターフェイスになります。From T to an interface type I in T's effective interface set and from T to any base interface of I. 実行時に T が値型の場合、変換はボックス化変換として実行されます。At run-time, if T is a value type, the conversion is executed as a boxing conversion. それ以外の場合、暗黙的な参照変換または id 変換として変換が実行されます。Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • T から型パラメーター Uには、TU (型パラメーターの制約) に依存しています。From T to a type parameter U, provided T depends on U (Type parameter constraints). 実行時に U が値型の場合、TU は必ず同じ型であり、変換は実行されません。At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. それ以外の場合、T が値型の場合、変換はボックス化変換として実行されます。Otherwise, if T is a value type, the conversion is executed as a boxing conversion. それ以外の場合、暗黙的な参照変換または id 変換として変換が実行されます。Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.
  • Null リテラルから Tに、指定された T は参照型であることがわかっています。From the null literal to T, provided T is known to be a reference type.
  • 参照型への暗黙的な変換が含まれている場合、T から参照型への変換が I 場合 S0 および S0 には Sへの id 変換が含まれます。From T to a reference type I if it has an implicit conversion to a reference type S0 and S0 has an identity conversion to S. 実行時には、S0への変換と同じ方法で変換が実行されます。At run-time the conversion is executed the same way as the conversion to S0.
  • インターフェイス型またはデリゲート I0 型への暗黙的な変換が含まれている場合は、T からインターフェイス型に I します。また、I0I (変位変換) に変換可能です。From T to an interface type I if it has an implicit conversion to an interface or delegate type I0 and I0 is variance-convertible to I (Variance conversion). 実行時に T が値型の場合、変換はボックス化変換として実行されます。At run-time, if T is a value type, the conversion is executed as a boxing conversion. それ以外の場合、暗黙的な参照変換または id 変換として変換が実行されます。Otherwise, the conversion is executed as an implicit reference conversion or identity conversion.

T が参照型 (型パラメーターの制約) であることがわかっている場合、上記の変換はすべて暗黙の参照変換 (暗黙の参照変換) として分類されます。If T is known to be a reference type (Type parameter constraints), the conversions above are all classified as implicit reference conversions (Implicit reference conversions). T が参照型でないことがわかっている場合、上記の変換はボックス化変換 (ボックス化変換) として分類されます。If T is not known to be a reference type, the conversions above are classified as boxing conversions (Boxing conversions).

ユーザー定義の暗黙的な変換User-defined implicit conversions

ユーザー定義の暗黙の変換は、省略可能な標準の暗黙的な変換で構成され、その後にユーザー定義の暗黙的な変換演算子の実行が続き、その後に省略可能な標準の暗黙的な変換が続きます。A user-defined implicit conversion consists of an optional standard implicit conversion, followed by execution of a user-defined implicit conversion operator, followed by another optional standard implicit conversion. ユーザー定義の暗黙の変換を評価するための正確な規則については、「ユーザー定義の暗黙的な変換の処理」を参照してください。The exact rules for evaluating user-defined implicit conversions are described in Processing of user-defined implicit conversions.

匿名関数の変換とメソッドグループの変換Anonymous function conversions and method group conversions

匿名関数とメソッドグループには、それ自体の型はありませんが、デリゲート型または式ツリー型に暗黙的に変換される場合があります。Anonymous functions and method groups do not have types in and of themselves, but may be implicitly converted to delegate types or expression tree types. 匿名関数の変換の詳細については、「匿名関数の変換」および「メソッドグループの変換」の「メソッドグループの変換」を参照してください。Anonymous function conversions are described in more detail in Anonymous function conversions and method group conversions in Method group conversions.

明示的な変換Explicit conversions

次の変換は、明示的な変換として分類されます。The following conversions are classified as explicit conversions:

  • すべての暗黙的な変換。All implicit conversions.
  • 明示的な数値変換。Explicit numeric conversions.
  • 明示的な列挙変換。Explicit enumeration conversions.
  • 明示的な null 許容型変換。Explicit nullable conversions.
  • 明示的な参照変換。Explicit reference conversions.
  • 明示的なインターフェイス変換。Explicit interface conversions.
  • 変換のボックス化を解除します。Unboxing conversions.
  • 明示的な動的変換Explicit dynamic conversions
  • ユーザー定義の明示的な変換。User-defined explicit conversions.

明示的な変換は、キャスト式 (キャスト式) で行うことができます。Explicit conversions can occur in cast expressions (Cast expressions).

明示的な変換のセットには、すべての暗黙的な変換が含まれます。The set of explicit conversions includes all implicit conversions. これは、冗長なキャスト式が許可されることを意味します。This means that redundant cast expressions are allowed.

暗黙的な変換ではない明示的な変換とは、常に成功することがわかっていることがわかっている変換、情報を失う可能性がある変換、および明示的に異なる型のドメイン間での変換です。表し.The explicit conversions that are not implicit conversions are conversions that cannot be proven to always succeed, conversions that are known to possibly lose information, and conversions across domains of types sufficiently different to merit explicit notation.

明示的な数値変換Explicit numeric conversions

明示的な数値変換は、 numeric_typeから別のnumeric_typeへの変換であり、暗黙的な数値変換 (暗黙的な数値変換) はまだ存在しません。The explicit numeric conversions are the conversions from a numeric_type to another numeric_type for which an implicit numeric conversion (Implicit numeric conversions) does not already exist:

  • sbyte から byteushortuintulongcharになります。From sbyte to byte, ushort, uint, ulong, or char.
  • byte から sbytecharになります。From byte to sbyte and char.
  • short から sbytebyteushortuintulongcharになります。From short to sbyte, byte, ushort, uint, ulong, or char.
  • ushort から sbytebyteshort、または charになります。From ushort to sbyte, byte, short, or char.
  • int から sbytebyteshortushortuintulongcharになります。From int to sbyte, byte, short, ushort, uint, ulong, or char.
  • uint から sbytebyteshortushortintcharになります。From uint to sbyte, byte, short, ushort, int, or char.
  • long から sbytebyteshortushortintuintulongcharになります。From long to sbyte, byte, short, ushort, int, uint, ulong, or char.
  • ulong から sbytebyteshortushortintuintlongcharになります。From ulong to sbyte, byte, short, ushort, int, uint, long, or char.
  • char から sbytebyte、または shortFrom char to sbyte, byte, or short.
  • float から sbytebyteshortushortintuintlongulongchardecimalになります。From float to sbyte, byte, short, ushort, int, uint, long, ulong, char, or decimal.
  • double から sbytebyteshortushortintuintlongulongcharfloatdecimalになります。From double to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or decimal.
  • decimal から sbytebyteshortushortintuintlongulongcharfloatdoubleになります。From decimal to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, or double.

明示的な変換には暗黙的な数値変換と明示的な数値変換がすべて含まれているため、キャスト式 (cast 式) を使用して任意のnumeric_typeから他の任意のnumeric_typeに変換することは常に可能です。Because the explicit conversions include all implicit and explicit numeric conversions, it is always possible to convert from any numeric_type to any other numeric_type using a cast expression (Cast expressions).

明示的な数値変換によって情報が失われるか、例外がスローされる可能性があります。The explicit numeric conversions possibly lose information or possibly cause exceptions to be thrown. 明示的な数値変換は、次のように処理されます。An explicit numeric conversion is processed as follows:

  • 整数型から別の整数型への変換では、変換が行われるオーバーフローチェックコンテキスト (checked および unchecked 演算子) によって処理が異なります。For a conversion from an integral type to another integral type, the processing depends on the overflow checking context (The checked and unchecked operators) in which the conversion takes place:
    • checked のコンテキストでは、ソースオペランドの値が変換先の型の範囲内にある場合、変換は成功しますが、ソースオペランドの値が変換先の型の範囲外である場合は、System.OverflowException をスローします。In a checked context, the conversion succeeds if the value of the source operand is within the range of the destination type, but throws a System.OverflowException if the value of the source operand is outside the range of the destination type.
    • unchecked のコンテキストでは、変換は常に成功し、次のように進行します。In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • 変換元の型が変換先の型より大きい場合、変換元の値はその "余分な" 最上位ビットを破棄することで切り詰められます。If the source type is larger than the destination type, then the source value is truncated by discarding its "extra" most significant bits. 結果は変換先の型の値として扱われます。The result is then treated as a value of the destination type.
      • 変換元の型が変換先の型より小さい場合、変換元の値は変換先の型と同じサイズになるように符号かゼロが拡張されます。If the source type is smaller than the destination type, then the source value is either sign-extended or zero-extended so that it is the same size as the destination type. 変換元の型に符号が付いている場合は符号拡張が利用され、符号が付いていない場合はゼロ拡張が利用されます。Sign-extension is used if the source type is signed; zero-extension is used if the source type is unsigned. 結果は変換先の型の値として扱われます。The result is then treated as a value of the destination type.
      • 変換元の型が変換先の型と同じサイズの場合、変換元の値は変換先の型の値として扱われます。If the source type is the same size as the destination type, then the source value is treated as a value of the destination type.
  • decimal から整数型への変換では、変換元の値が、最も近い整数値に0方向に丸められます。この整数値は変換の結果になります。For a conversion from decimal to an integral type, the source value is rounded towards zero to the nearest integral value, and this integral value becomes the result of the conversion. 結果の整数値が変換先の型の範囲外になると、System.OverflowException がスローされます。If the resulting integral value is outside the range of the destination type, a System.OverflowException is thrown.
  • float または double から整数型への変換の場合、処理は、変換が行われるオーバーフローチェックコンテキスト (checked および unchecked 演算子) に依存します。For a conversion from float or double to an integral type, the processing depends on the overflow checking context (The checked and unchecked operators) in which the conversion takes place:
    • checked のコンテキストでは、変換は次のように行われます。In a checked context, the conversion proceeds as follows:
      • オペランドの値が NaN または無限の場合は、System.OverflowException がスローされます。If the value of the operand is NaN or infinite, a System.OverflowException is thrown.
      • それ以外の場合、ソースオペランドは0方向に最も近い整数値に丸められます。Otherwise, the source operand is rounded towards zero to the nearest integral value. この整数値が変換先の型の範囲内にある場合、この値は変換の結果になります。If this integral value is within the range of the destination type then this value is the result of the conversion.
      • それ以外の場合は、System.OverflowException がスローされます。Otherwise, a System.OverflowException is thrown.
    • unchecked のコンテキストでは、変換は常に成功し、次のように進行します。In an unchecked context, the conversion always succeeds, and proceeds as follows.
      • オペランドの値が NaN または無限の場合、変換の結果は、変換先の型の指定されていない値になります。If the value of the operand is NaN or infinite, the result of the conversion is an unspecified value of the destination type.
      • それ以外の場合、ソースオペランドは0方向に最も近い整数値に丸められます。Otherwise, the source operand is rounded towards zero to the nearest integral value. この整数値が変換先の型の範囲内にある場合、この値は変換の結果になります。If this integral value is within the range of the destination type then this value is the result of the conversion.
      • それ以外の場合、変換の結果は、変換先の型の指定されていない値になります。Otherwise, the result of the conversion is an unspecified value of the destination type.
  • double から floatへの変換では、double 値は最も近い float 値に丸められます。For a conversion from double to float, the double value is rounded to the nearest float value. double 値が小さすぎて floatとして表現できない場合、結果は正のゼロまたは負のゼロになります。If the double value is too small to represent as a float, the result becomes positive zero or negative zero. double 値が大きすぎて floatとして表現できない場合、結果は正の無限大または負の無限大になります。If the double value is too large to represent as a float, the result becomes positive infinity or negative infinity. double 値が NaN の場合、結果も NaN になります。If the double value is NaN, the result is also NaN.
  • float または double から decimalへの変換では、変換元の値が decimal 表現に変換され、必要に応じて28進数の小数点以下の最も近い数値に丸められます (10 進数型)。For a conversion from float or double to decimal, the source value is converted to decimal representation and rounded to the nearest number after the 28th decimal place if required (The decimal type). ソース値が小さすぎて decimalとして表現できない場合、結果は0になります。If the source value is too small to represent as a decimal, the result becomes zero. ソース値が NaN、無限大、または大きすぎて decimalとして表すことができない場合は、System.OverflowException がスローされます。If the source value is NaN, infinity, or too large to represent as a decimal, a System.OverflowException is thrown.
  • decimal から float または doubleへの変換では、decimal 値は最も近い double または float 値に丸められます。For a conversion from decimal to float or double, the decimal value is rounded to the nearest double or float value. この変換によって精度が失われる場合がありますが、例外がスローされることはありません。While this conversion may lose precision, it never causes an exception to be thrown.

明示的な列挙変換Explicit enumeration conversions

明示的な列挙変換は次のとおりです。The explicit enumeration conversions are:

  • sbytebyteshortushortintuintlongulongcharfloatdoubledecimal を任意のenum_typeにします。From sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal to any enum_type.
  • 任意のenum_typeから sbytebyteshortushortintuintlongulongcharfloatdoubledecimalになります。From any enum_type to sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, or decimal.
  • 任意のenum_typeから他のenum_typeに。From any enum_type to any other enum_type.

2つの型の間の明示的な列挙型変換は、参加しているenum_typeenum_typeの基になる型として扱い、結果の型間で暗黙的または明示的な数値変換を実行することによって処理されます。An explicit enumeration conversion between two types is processed by treating any participating enum_type as the underlying type of that enum_type, and then performing an implicit or explicit numeric conversion between the resulting types. たとえば、および基になる型が intenum_type E 場合、E から byte への変換は、int から byteへの明示的な数値変換 (明示的な数値変換) として処理され、byte から E への変換は暗黙的な数値変換 (暗黙的な数値変換) として処理されます。For example, given an enum_type E with and underlying type of int, a conversion from E to byte is processed as an explicit numeric conversion (Explicit numeric conversions) from int to byte, and a conversion from byte to E is processed as an implicit numeric conversion (Implicit numeric conversions) from byte to int.

明示的な null 許容変換Explicit nullable conversions

明示的な null 許容型変換では、null 非許容の値型に対して動作する定義済みの明示的な変換が許可され、これらの型の null 許容形式でも使用できます。Explicit nullable conversions permit predefined explicit conversions that operate on non-nullable value types to also be used with nullable forms of those types. Null 非許容値 S 型から T null 非許容の値型への変換を行う定義済みの明示的な変換 (id 変換暗黙的な数値変換暗黙的な列挙変換明示的な数値変換、明示的な列挙変換) には、次の null 許容変換が存在します。For each of the predefined explicit conversions that convert from a non-nullable value type S to a non-nullable value type T (Identity conversion, Implicit numeric conversions, Implicit enumeration conversions, Explicit numeric conversions, and Explicit enumeration conversions), the following nullable conversions exist:

  • S? から T?への明示的な変換。An explicit conversion from S? to T?.
  • S から T?への明示的な変換。An explicit conversion from S to T?.
  • S? から Tへの明示的な変換。An explicit conversion from S? to T.

S から T への基になる変換に基づく null 許容型変換の評価は次のように行われます。Evaluation of a nullable conversion based on an underlying conversion from S to T proceeds as follows:

  • Null 許容型変換が S? から T?の場合は、次のようになります。If the nullable conversion is from S? to T?:
    • ソース値が null (HasValue プロパティが false) の場合、結果は T?型の null 値になります。If the source value is null (HasValue property is false), the result is the null value of type T?.
    • それ以外の場合、変換は S? から Sへのラップ解除として評価された後、S から Tへの基になる変換と、その後に T から T?へのラップが行われます。Otherwise, the conversion is evaluated as an unwrapping from S? to S, followed by the underlying conversion from S to T, followed by a wrapping from T to T?.
  • Null 許容型変換が S から T?に対して行われる場合、変換は S から T の基になる変換として評価され、その後、T から T?へのラップが行われます。If the nullable conversion is from S to T?, the conversion is evaluated as the underlying conversion from S to T followed by a wrapping from T to T?.
  • Null 許容型変換が S? から Tに対して行われる場合、変換は S? から S のラップ解除として評価され、その後に S から Tへの基になる変換が行われます。If the nullable conversion is from S? to T, the conversion is evaluated as an unwrapping from S? to S followed by the underlying conversion from S to T.

Null 許容値のラップを解除しようとすると、値が null場合に例外がスローされることに注意してください。Note that an attempt to unwrap a nullable value will throw an exception if the value is null.

明示的な参照変換Explicit reference conversions

明示的な参照変換は次のとおりです。The explicit reference conversions are:

  • object から、他のreference_typedynamic します。From object and dynamic to any other reference_type.
  • 任意のclass_type S から任意のclass_type Tへの S は、Tの基本クラスです。From any class_type S to any class_type T, provided S is a base class of T.
  • 任意のclass_type S から任意のinterface_type Tへの S はシールされていませんが、S は実装されていません。From any class_type S to any interface_type T, provided S is not sealed and provided S does not implement T.
  • 任意のinterface_type Tclass_type S から、T を実装 T がシールされていない、または指定されている場合は、Sを実装します。From any interface_type S to any class_type T, provided T is not sealed or provided T implements S.
  • 任意のinterface_type S から、STから派生したものではなく、任意のinterface_type Tになります。From any interface_type S to any interface_type T, provided S is not derived from T.
  • 要素型が Tarray_type S から、次のすべてが満たされていれば、要素型が TEarray_typeSE ます。From an array_type S with an element type SE to an array_type T with an element type TE, provided all of the following are true:
    • ST は要素の型のみが異なります。S and T differ only in element type. 言い換えると、ST の次元数が同じになります。In other words, S and T have the same number of dimensions.
    • SETE は両方ともreference_typeです。Both SE and TE are reference_types.
    • SE から TEへの明示的な参照変換が存在します。An explicit reference conversion exists from SE to TE.
  • System.Array と、それが実装するインターフェイスから、任意のarray_typeにします。From System.Array and the interfaces it implements to any array_type.
  • S から Tへの明示的な参照変換がある場合は、1次元配列型から System.Collections.Generic.IList<T> とその基本インターフェイスを S[] します。From a single-dimensional array type S[] to System.Collections.Generic.IList<T> and its base interfaces, provided that there is an explicit reference conversion from S to T.
  • S から Tへの明示的な id または参照の変換がある場合は、System.Collections.Generic.IList<S> とその基本インターフェイスから、T[]にします。From System.Collections.Generic.IList<S> and its base interfaces to a single-dimensional array type T[], provided that there is an explicit identity or reference conversion from S to T.
  • System.Delegate と、それが実装するインターフェイスから、任意のdelegate_typeにします。From System.Delegate and the interfaces it implements to any delegate_type.
  • 参照型から参照型への明示的な参照変換がある場合は T 参照型から参照型への明示的な参照変換があり、T0 には Tの id 変換がある場合は T0From a reference type to a reference type T if it has an explicit reference conversion to a reference type T0 and T0 has an identity conversion T.
  • 参照型からインターフェイスまたはデリゲート型への明示的な参照変換が含まれている場合 T、その型がインターフェイスまたはデリゲート T0 型への明示的な参照変換を持っている場合、または T0T に変換可能であるか T に変換可能かどうかを示します (分散変換)。From a reference type to an interface or delegate type T if it has an explicit reference conversion to an interface or delegate type T0 and either T0 is variance-convertible to T or T is variance-convertible to T0 (Variance conversion).
  • D<S1...Sn> から D<T1...Tn> D<X1...Xn> が汎用デリゲート型である場合、D<S1...Sn>D<T1...Tn>との互換性がないか、Xi の型パラメーター D ごとに次のようになります。From D<S1...Sn> to D<T1...Tn> where D<X1...Xn> is a generic delegate type, D<S1...Sn> is not compatible with or identical to D<T1...Tn>, and for each type parameter Xi of D the following holds:
    • Xi が不変の場合、SiTiと同じになります。If Xi is invariant, then Si is identical to Ti.
    • Xi が共変の場合は、Si から Tiへの暗黙的または明示的な id または参照の変換が存在します。If Xi is covariant, then there is an implicit or explicit identity or reference conversion from Si to Ti.
    • Xi が反変の場合、SiTi は両方とも同じか、または両方の参照型になります。If Xi is contravariant, then Si and Ti are either identical or both reference types.
  • 参照型として認識されている型パラメーターを使用する明示的な変換。Explicit conversions involving type parameters that are known to be reference types. 型パラメーターを使用する明示的な変換の詳細については、「型パラメーターを使用した明示的な変換」を参照してください。For more details on explicit conversions involving type parameters, see Explicit conversions involving type parameters.

明示的な参照変換とは、それらが正しいことを確認するためにランタイムチェックを必要とする参照型間の変換です。The explicit reference conversions are those conversions between reference-types that require run-time checks to ensure they are correct.

実行時に明示的な参照変換を成功させるには、ソースオペランドの値が nullであるか、またはソースオペランドによって参照されるオブジェクトの実際の型が、暗黙的な参照変換 (暗黙の参照変換) またはボックス化変換 (ボックス化変換) によって対象の型に変換できる型である必要があります。For an explicit reference conversion to succeed at run-time, the value of the source operand must be null, or the actual type of the object referenced by the source operand must be a type that can be converted to the destination type by an implicit reference conversion (Implicit reference conversions) or boxing conversion (Boxing conversions). 明示的な参照変換が失敗すると、System.InvalidCastException がスローされます。If an explicit reference conversion fails, a System.InvalidCastException is thrown.

暗黙的または明示的な参照変換では、変換するオブジェクトの参照 id は変更されません。Reference conversions, implicit or explicit, never change the referential identity of the object being converted. つまり、参照変換によって参照の型が変更されても、参照先のオブジェクトの型または値が変更されることはありません。In other words, while a reference conversion may change the type of the reference, it never changes the type or value of the object being referred to.

ボックス化解除Unboxing conversions

ボックス化解除変換は、参照型を明示的にvalue_typeに変換することを許可します。An unboxing conversion permits a reference type to be explicitly converted to a value_type. ボックス化解除変換は、型 objectdynamic および System.ValueType から任意のnon_nullable_value_typeに、任意のinterface_typeからnon_nullable_value_typeを実装する任意のinterface_typeに変換されます。An unboxing conversion exists from the types object, dynamic and System.ValueType to any non_nullable_value_type, and from any interface_type to any non_nullable_value_type that implements the interface_type. さらに、型 System.Enum を任意のenum_typeにボックス化解除できます。Furthermore type System.Enum can be unboxed to any enum_type.

参照型からnullable_typeの基になるnon_nullable_value_typeにアンボックス変換が存在する場合、参照型からnullable_typeへのアンボックス変換が存在します。An unboxing conversion exists from a reference type to a nullable_type if an unboxing conversion exists from the reference type to the underlying non_nullable_value_type of the nullable_type.

インターフェイス I0 型からのアンボックス変換があり、I0Iへの id 変換を持っている場合、S 値型には、インターフェイス型から I のボックス化変換があります。A value type S has an unboxing conversion from an interface type I if it has an unboxing conversion from an interface type I0 and I0 has an identity conversion to I.

インターフェイス型またはデリゲート I0 型からのアンボックス変換がある場合、または I0I に対して分散変換可能であるか、I に変換可能かどうか I0 (変位変換) である場合、値型 S は、インターフェイス型からのボックス化変換を I ます。A value type S has an unboxing conversion from an interface type I if it has an unboxing conversion from an interface or delegate type I0 and either I0 is variance-convertible to I or I is variance-convertible to I0 (Variance conversion).

ボックス化解除操作は、最初にオブジェクトインスタンスが、指定されたvalue_typeのボックス化された値であることを確認し、次にインスタンスから値をコピーすることで構成されます。An unboxing operation consists of first checking that the object instance is a boxed value of the given value_type, and then copying the value out of the instance. Nullable_typeへの null 参照のボックス化を解除すると、 nullable_typeの null 値が生成されます。Unboxing a null reference to a nullable_type produces the null value of the nullable_type. 構造体は、すべての構造体 (継承) の基本クラスであるため、System.ValueType型からのボックス化を解除できます。A struct can be unboxed from the type System.ValueType, since that is a base class for all structs (Inheritance).

ボックス化解除変換の詳細については、「ボックス化変換」を参照してください。Unboxing conversions are described further in Unboxing conversions.

明示的な動的変換Explicit dynamic conversions

明示的な動的変換は、dynamic 型の式から T任意の型に存在します。An explicit dynamic conversion exists from an expression of type dynamic to any type T. 変換は動的にバインドされます (動的バインド)。これは、Tする式の実行時の型から、実行時に明示的な変換が行われることを意味します。The conversion is dynamically bound (Dynamic binding), which means that an explicit conversion will be sought at run-time from the run-time type of the expression to T. 変換が見つからない場合は、実行時例外がスローされます。If no conversion is found, a run-time exception is thrown.

変換の動的バインドが望ましくない場合は、式を最初に objectに変換し、次に目的の型に変換できます。If dynamic binding of the conversion is not desired, the expression can be first converted to object, and then to the desired type.

次のクラスが定義されているとします。Assume the following class is defined:

class C
{
    int i;

    public C(int i) { this.i = i; }

    public static explicit operator C(string s) 
    {
        return new C(int.Parse(s));
    }
}

明示的な動的変換の例を次に示します。The following example illustrates explicit dynamic conversions:

object o  = "1";
dynamic d = "2";

var c1 = (C)o; // Compiles, but explicit reference conversion fails
var c2 = (C)d; // Compiles and user defined conversion succeeds

o から C への最適な変換は、明示的な参照変換としてコンパイル時に検出されます。The best conversion of o to C is found at compile-time to be an explicit reference conversion. これは、実際には "1"Cではないため、実行時に失敗します。This fails at run-time, because "1" is not in fact a C. ただし、d から C への変換は、明示的な動的変換として実行時に中断されます。実行時には、d -- の実行時の型から string へのユーザー定義の変換が検出され、成功します。The conversion of d to C however, as an explicit dynamic conversion, is suspended to run-time, where a user defined conversion from the run-time type of d -- string -- to C is found, and succeeds.

型パラメーターを含む明示的な変換Explicit conversions involving type parameters

指定された型パラメーター Tには、次の明示的な変換が存在します。The following explicit conversions exist for a given type parameter T:

  • T の有効な基本クラス C から、C の任意の基底クラスから TT します。From the effective base class C of T to T and from any base class of C to T. 実行時に T が値型の場合、変換はボックス化解除変換として実行されます。At run-time, if T is a value type, the conversion is executed as an unboxing conversion. それ以外の場合は、明示的な参照変換または id 変換として変換が実行されます。Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • 任意のインターフェイス型から Tします。From any interface type to T. 実行時に T が値型の場合、変換はボックス化解除変換として実行されます。At run-time, if T is a value type, the conversion is executed as an unboxing conversion. それ以外の場合は、明示的な参照変換または id 変換として変換が実行されます。Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • T から Iへの暗黙的な変換は行われていませんが、指定されたすべてのinterface_type IT ます。From T to any interface_type I provided there is not already an implicit conversion from T to I. 実行時に T が値型の場合、変換はボックス化変換として実行され、その後に明示的な参照変換が行われます。At run-time, if T is a value type, the conversion is executed as a boxing conversion followed by an explicit reference conversion. それ以外の場合は、明示的な参照変換または id 変換として変換が実行されます。Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
  • 型パラメーターから Tへの U は、TU (型パラメーターの制約) に依存しています。From a type parameter U to T, provided T depends on U (Type parameter constraints). 実行時に U が値型の場合、TU は必ず同じ型であり、変換は実行されません。At run-time, if U is a value type, then T and U are necessarily the same type and no conversion is performed. それ以外の場合、T が値型の場合、変換はボックス化解除変換として実行されます。Otherwise, if T is a value type, the conversion is executed as an unboxing conversion. それ以外の場合は、明示的な参照変換または id 変換として変換が実行されます。Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.

T が参照型であることがわかっている場合、上記の変換はすべて、明示的な参照変換 (明示的な参照変換) として分類されます。If T is known to be a reference type, the conversions above are all classified as explicit reference conversions (Explicit reference conversions). T が参照型でないことがわかっている場合、上記の変換は、ボックス化解除変換 (ボックス化解除) として分類されます。If T is not known to be a reference type, the conversions above are classified as unboxing conversions (Unboxing conversions).

上記のルールでは、制約のない型パラメーターから非インターフェイス型への直接明示的な変換は許可されていません。The above rules do not permit a direct explicit conversion from an unconstrained type parameter to a non-interface type, which might be surprising. このルールの理由は、混乱を防ぎ、そのような変換のセマンティクスを明確にするためです。The reason for this rule is to prevent confusion and make the semantics of such conversions clear. たとえば、次のような宣言があるとします。For example, consider the following declaration:

class X<T>
{
    public static long F(T t) {
        return (long)t;                // Error 
    }
}

t から int への直接的な明示的な変換が許可されている場合は、X<int>.F(7) が 7Lを返すことが簡単であると考えられます。If the direct explicit conversion of t to int were permitted, one might easily expect that X<int>.F(7) would return 7L. ただし、標準の数値変換は、バインド時に型が数値であることがわかっている場合にのみ考慮されるため、そうではありません。However, it would not, because the standard numeric conversions are only considered when the types are known to be numeric at binding-time. このようなセマンティクスを明確にするために、上記の例を記述する必要があります。In order to make the semantics clear, the above example must instead be written:

class X<T>
{
    public static long F(T t) {
        return (long)(object)t;        // Ok, but will only work when T is long
    }
}

このコードはコンパイルされるようになりましたが、実行時に X<int>.F(7) を実行すると、ボックス化された intlongに直接変換できないため、例外がスローされます。This code will now compile but executing X<int>.F(7) would then throw an exception at run-time, since a boxed int cannot be converted directly to a long.

ユーザー定義の明示的な変換User-defined explicit conversions

ユーザー定義の明示的な変換は、省略可能な標準の明示的な変換で構成され、その後にユーザー定義の暗黙的または明示的な変換演算子を実行した後に、別のオプションで標準の明示的な変換を実行します。A user-defined explicit conversion consists of an optional standard explicit conversion, followed by execution of a user-defined implicit or explicit conversion operator, followed by another optional standard explicit conversion. ユーザー定義の明示的な変換を評価するための正確な規則については、「ユーザー定義の明示的な変換の処理」を参照してください。The exact rules for evaluating user-defined explicit conversions are described in Processing of user-defined explicit conversions.

標準変換Standard conversions

標準変換は、ユーザー定義の変換の一部として発生する可能性のある定義済みの変換です。The standard conversions are those pre-defined conversions that can occur as part of a user-defined conversion.

標準の暗黙的な変換Standard implicit conversions

次の暗黙の変換は、標準の暗黙的な変換として分類されます。The following implicit conversions are classified as standard implicit conversions:

標準の暗黙の変換は、明示的にユーザー定義の暗黙的な変換を除外します。The standard implicit conversions specifically exclude user-defined implicit conversions.

標準の明示的な変換Standard explicit conversions

標準の明示的な変換は、すべての標準の暗黙的な変換に加え、逆の標準の暗黙的な変換が存在する明示的な変換のサブセットを加えたものです。The standard explicit conversions are all standard implicit conversions plus the subset of the explicit conversions for which an opposite standard implicit conversion exists. 言い換えると、標準の暗黙的な変換が型 A から B型に存在する場合は、型 A から型 B および型の B への標準の明示的な変換が存在します。In other words, if a standard implicit conversion exists from a type A to a type B, then a standard explicit conversion exists from type A to type B and from type B to type A.

ユーザー定義の変換User-defined conversions

C#定義済みの暗黙的な変換と明示的な変換を、ユーザー定義の変換によって拡張できるようにします。C# allows the pre-defined implicit and explicit conversions to be augmented by user-defined conversions. ユーザー定義の変換は、クラスおよび構造体型の変換演算子 (変換演算子) を宣言することによって導入されます。User-defined conversions are introduced by declaring conversion operators (Conversion operators) in class and struct types.

許可されたユーザー定義変換Permitted user-defined conversions

C#特定のユーザー定義変換のみを宣言できます。C# permits only certain user-defined conversions to be declared. 特に、既存の暗黙的または明示的な変換を再定義することはできません。In particular, it is not possible to redefine an already existing implicit or explicit conversion.

指定されたソース型 S とターゲット型 Tの場合、S または T が null 許容型である場合は、S0T0 がその基になる型を参照するようにします。それ以外の場合、S0T0 はそれぞれ ST になります。For a given source type S and target type T, if S or T are nullable types, let S0 and T0 refer to their underlying types, otherwise S0 and T0 are equal to S and T respectively. クラスまたは構造体は、次のすべての条件を満たす場合にのみ、ソース S 型からターゲット T 型への変換を宣言することができます。A class or struct is permitted to declare a conversion from a source type S to a target type T only if all of the following are true:

  • S0T0 の種類は異なります。S0 and T0 are different types.
  • S0 または T0 は、演算子の宣言が行われるクラスまたは構造体の型です。Either S0 or T0 is the class or struct type in which the operator declaration takes place.
  • S0T0interface_typeではありません。Neither S0 nor T0 is an interface_type.
  • ユーザー定義の変換を除外すると、S から T または T から Sへの変換は存在しません。Excluding user-defined conversions, a conversion does not exist from S to T or from T to S.

ユーザー定義の変換に適用される制限については、「変換演算子」で詳しく説明します。The restrictions that apply to user-defined conversions are discussed further in Conversion operators.

リフト変換演算子Lifted conversion operators

Null 非許容の値 S 型から null 非許容の値 T型に変換するユーザー定義の変換演算子を指定した場合、S? から T?に変換するリフトされた変換演算子が存在します。Given a user-defined conversion operator that converts from a non-nullable value type S to a non-nullable value type T, a lifted conversion operator exists that converts from S? to T?. このリフトされた変換演算子は、S? から S へのラップ解除を実行します。その後、S から T へのユーザー定義変換と、T から T?へのラップが実行されます。ただし、null 値 S? は null 値 T?に直接変換されます。This lifted conversion operator performs an unwrapping from S? to S followed by the user-defined conversion from S to T followed by a wrapping from T to T?, except that a null valued S? converts directly to a null valued T?.

リフトされた変換演算子には、基になるユーザー定義変換演算子と同じ暗黙的または明示的な分類があります。A lifted conversion operator has the same implicit or explicit classification as its underlying user-defined conversion operator. "ユーザー定義変換" という用語は、ユーザー定義変換演算子とリフト変換演算子の両方を使用する場合に適用されます。The term "user-defined conversion" applies to the use of both user-defined and lifted conversion operators.

ユーザー定義変換の評価Evaluation of user-defined conversions

ユーザー定義の変換は、ソース型と呼ばれる型の値を、ターゲット型と呼ばれる別の型に変換します。A user-defined conversion converts a value from its type, called the source type, to another type, called the target type. ユーザー定義の変換の評価では、特定のソースとターゲットの種類に対して最も限定的なユーザー定義変換演算子が検索されます。Evaluation of a user-defined conversion centers on finding the most specific user-defined conversion operator for the particular source and target types. この決定は、次のいくつかの手順に分かれています。This determination is broken into several steps:

  • ユーザー定義の変換演算子が考慮されるクラスと構造体のセットを検索します。Finding the set of classes and structs from which user-defined conversion operators will be considered. このセットは、ソースの型とその基本クラス、およびターゲットの型とその基本クラスで構成されます (クラスと構造体のみがユーザー定義の演算子を宣言できること、および非クラス型には基底クラスがないという暗黙の想定があります)。This set consists of the source type and its base classes and the target type and its base classes (with the implicit assumptions that only classes and structs can declare user-defined operators, and that non-class types have no base classes). この手順では、ソースまたはターゲットのどちらかの型がnullable_typeの場合、基になる型が代わりに使用されます。For the purposes of this step, if either the source or target type is a nullable_type, their underlying type is used instead.
  • この一連の型から、適用可能なユーザー定義およびリフト変換演算子を決定します。From that set of types, determining which user-defined and lifted conversion operators are applicable. 変換演算子を適用できるようにするには、ソース型から演算子のオペランド型への標準変換 (標準変換) を実行できる必要があります。また、演算子の結果型からターゲット型への標準変換を実行できる必要があります。For a conversion operator to be applicable, it must be possible to perform a standard conversion (Standard conversions) from the source type to the operand type of the operator, and it must be possible to perform a standard conversion from the result type of the operator to the target type.
  • 適用可能なユーザー定義演算子のセットから、明確に特定できる演算子を決定します。From the set of applicable user-defined operators, determining which operator is unambiguously the most specific. 一般的に、最も具体的な演算子は、変換元の型に対してオペランドの型が "最も近い" 演算子で、結果の型が対象の型に "最も近い" になります。In general terms, the most specific operator is the operator whose operand type is "closest" to the source type and whose result type is "closest" to the target type. ユーザー定義の変換演算子は、リフト変換演算子よりも優先されます。User-defined conversion operators are preferred over lifted conversion operators. 特定のユーザー定義変換演算子を設定するための正確な規則は、次のセクションで定義されています。The exact rules for establishing the most specific user-defined conversion operator are defined in the following sections.

最も限定的なユーザー定義変換演算子が特定されたら、ユーザー定義変換の実際の実行では、次の3つの手順が必要になります。Once a most specific user-defined conversion operator has been identified, the actual execution of the user-defined conversion involves up to three steps:

  • 最初に、必要に応じて、変換元の型からユーザー定義またはリフトされた変換演算子のオペランドの型への標準変換を実行します。First, if required, performing a standard conversion from the source type to the operand type of the user-defined or lifted conversion operator.
  • 次に、ユーザー定義変換演算子またはリフト変換演算子を呼び出して変換を実行します。Next, invoking the user-defined or lifted conversion operator to perform the conversion.
  • 最後に、必要に応じて、ユーザー定義またはリフトされた変換演算子の結果型から対象の型への標準変換を実行します。Finally, if required, performing a standard conversion from the result type of the user-defined or lifted conversion operator to the target type.

ユーザー定義の変換の評価では、複数のユーザー定義変換演算子またはリフト変換演算子は必要ありません。Evaluation of a user-defined conversion never involves more than one user-defined or lifted conversion operator. 言い換えると、型 S から型 T への変換では、最初に S から X へのユーザー定義変換が実行され、次に X から Tへのユーザー定義変換が実行されることはありません。In other words, a conversion from type S to type T will never first execute a user-defined conversion from S to X and then execute a user-defined conversion from X to T.

ユーザー定義の暗黙的または明示的な変換の評価の正確な定義については、次のセクションで説明します。Exact definitions of evaluation of user-defined implicit or explicit conversions are given in the following sections. 定義では、次の用語が使用されます。The definitions make use of the following terms:

  • 標準の暗黙的な変換 (標準の暗黙的な変換) が型 A から B型に存在する場合、AB も*interface_type****に含ま***れていないと、AB***を包含し***ていると言います。If a standard implicit conversion (Standard implicit conversions) exists from a type A to a type B, and if neither A nor B are interface_types, then A is said to be encompassed by B, and B is said to encompass A.
  • 型のセットの中で最も外側にある型は、セット内の他のすべての型を含む1つの型です。The most encompassing type in a set of types is the one type that encompasses all other types in the set. 1つの型に他のすべての型が含まれていない場合、そのセットには最も外側の型がありません。If no single type encompasses all other types, then the set has no most encompassing type. より直観的な用語では、最も外側の型は、セット内の "最大" 型です。これは、他の型を暗黙的に変換できる1つの型です。In more intuitive terms, the most encompassing type is the "largest" type in the set—the one type to which each of the other types can be implicitly converted.
  • 型のセットの中で最も内側にある型は、セット内の他のすべての型に包含されている型です。The most encompassed type in a set of types is the one type that is encompassed by all other types in the set. 他のすべての型に包含されている型がない場合は、そのセットに最も包含されていない型はありません。If no single type is encompassed by all other types, then the set has no most encompassed type. より直観的な用語では、最も包含されている型は、セット内の "最小" 型です。これは、他の型に暗黙的に変換できる1つの型です。In more intuitive terms, the most encompassed type is the "smallest" type in the set—the one type that can be implicitly converted to each of the other types.

ユーザー定義の暗黙的な変換の処理Processing of user-defined implicit conversions

S から型 T へのユーザー定義の暗黙的な変換は、次のように処理されます。A user-defined implicit conversion from type S to type T is processed as follows:

  • S0T0の種類を決定します。Determine the types S0 and T0. S または T が null 許容型である場合、S0T0 はその基になる型です。それ以外の場合は、S0T0 がそれぞれ ST になります。If S or T are nullable types, S0 and T0 are their underlying types, otherwise S0 and T0 are equal to S and T respectively.
  • ユーザー定義の変換演算子が考慮される型のセット (D) を検索します。Find the set of types, D, from which user-defined conversion operators will be considered. このセットは、S0 (S0 がクラスまたは構造体である場合)、S0 の基本クラス (S0 がクラスの場合)、T0 (T0 がクラスまたは構造体の場合) で構成されます。This set consists of S0 (if S0 is a class or struct), the base classes of S0 (if S0 is a class), and T0 (if T0 is a class or struct).
  • 適用可能なユーザー定義およびリフト変換演算子のセットを検索し、Uします。Find the set of applicable user-defined and lifted conversion operators, U. このセットは、S を含む型から Tに含まれる型への変換を行う D のクラスまたは構造体によって宣言された、ユーザー定義の、リフトされた暗黙の変換演算子で構成されます。This set consists of the user-defined and lifted implicit conversion operators declared by the classes or structs in D that convert from a type encompassing S to a type encompassed by T. U が空の場合、変換は定義されていないため、コンパイル時エラーが発生します。If U is empty, the conversion is undefined and a compile-time error occurs.
  • U内の演算子の最も具体的なソースの種類である SXを検索します。Find the most specific source type, SX, of the operators in U:
    • U 内のいずれかの演算子が Sから変換される場合、SXSます。If any of the operators in U convert from S, then SX is S.
    • それ以外の場合、SXU内の演算子のソースの種類の組み合わせにおいて最も包含されている型です。Otherwise, SX is the most encompassed type in the combined set of source types of the operators in U. 最も包含されている型が1つだけ見つからない場合、変換はあいまいで、コンパイル時エラーが発生します。If exactly one most encompassed type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • U内の演算子の最も具体的な対象の型である TXを検索します。Find the most specific target type, TX, of the operators in U:
    • U のいずれかの演算子が Tに変換される場合、TXTます。If any of the operators in U convert to T, then TX is T.
    • それ以外の場合、TX は、U内の演算子の対象の型を組み合わせたセット内で最も外側にある型になります。Otherwise, TX is the most encompassing type in the combined set of target types of the operators in U. 最も外側の型が1つだけ見つからない場合、変換はあいまいで、コンパイル時エラーが発生します。If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • 最も具体的な変換演算子を見つけます。Find the most specific conversion operator:
    • SX から TXに変換するユーザー定義の変換演算子を1つだけ含む U 場合は、これが最も具体的な変換演算子です。If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • それ以外の U 場合、SX から TXに変換するリフト変換演算子が1つだけ含まれている場合は、これが最も具体的な変換演算子になります。Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • それ以外の場合、変換はあいまいで、コンパイル時エラーが発生します。Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • 最後に、変換を適用します。Finally, apply the conversion:
    • SSXない場合は、S から SX への標準の暗黙的な変換が実行されます。If S is not SX, then a standard implicit conversion from S to SX is performed.
    • SX から TXに変換するために、最も具体的な変換演算子が呼び出されます。The most specific conversion operator is invoked to convert from SX to TX.
    • TXTない場合は、TX から T への標準の暗黙的な変換が実行されます。If TX is not T, then a standard implicit conversion from TX to T is performed.

ユーザー定義の明示的な変換の処理Processing of user-defined explicit conversions

S 型から T 型へのユーザー定義の明示的な変換は、次のように処理されます。A user-defined explicit conversion from type S to type T is processed as follows:

  • S0T0の種類を決定します。Determine the types S0 and T0. S または T が null 許容型である場合、S0T0 はその基になる型です。それ以外の場合は、S0T0 がそれぞれ ST になります。If S or T are nullable types, S0 and T0 are their underlying types, otherwise S0 and T0 are equal to S and T respectively.
  • ユーザー定義の変換演算子が考慮される型のセット (D) を検索します。Find the set of types, D, from which user-defined conversion operators will be considered. このセットは、S0 (S0 がクラスまたは構造体である場合)、S0 の基本クラス (S0 がクラスの場合)、T0 (T0 がクラスまたは構造体の場合)、T0 の基本クラス (T0 がクラスの場合) で構成されます。This set consists of S0 (if S0 is a class or struct), the base classes of S0 (if S0 is a class), T0 (if T0 is a class or struct), and the base classes of T0 (if T0 is a class).
  • 適用可能なユーザー定義およびリフト変換演算子のセットを検索し、Uします。Find the set of applicable user-defined and lifted conversion operators, U. このセットは、S によって包含または包含されている型を Tによって包含または包含されている型に変換する、D のクラスまたは構造体によって宣言された、ユーザー定義の、リフトされた暗黙的または明示的な変換演算子で構成されます。This set consists of the user-defined and lifted implicit or explicit conversion operators declared by the classes or structs in D that convert from a type encompassing or encompassed by S to a type encompassing or encompassed by T. U が空の場合、変換は定義されていないため、コンパイル時エラーが発生します。If U is empty, the conversion is undefined and a compile-time error occurs.
  • U内の演算子の最も具体的なソースの種類である SXを検索します。Find the most specific source type, SX, of the operators in U:
    • U 内のいずれかの演算子が Sから変換される場合、SXSます。If any of the operators in U convert from S, then SX is S.
    • それ以外の場合、U 内のいずれかの演算子が Sを含む型から変換される場合、SX は、それらの演算子のソース型の組み合わせで最も包含されている型になります。Otherwise, if any of the operators in U convert from types that encompass S, then SX is the most encompassed type in the combined set of source types of those operators. 最も包含されていない型が見つからない場合は、変換があいまいになり、コンパイル時エラーが発生します。If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
    • それ以外の場合、SXU内の演算子のソースの種類の組み合わせにおいて最も外側の型になります。Otherwise, SX is the most encompassing type in the combined set of source types of the operators in U. 最も外側の型が1つだけ見つからない場合、変換はあいまいで、コンパイル時エラーが発生します。If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
  • U内の演算子の最も具体的な対象の型である TXを検索します。Find the most specific target type, TX, of the operators in U:
    • U のいずれかの演算子が Tに変換される場合、TXTます。If any of the operators in U convert to T, then TX is T.
    • それ以外の場合、U 内のいずれかの演算子が Tによって包含されている型に変換される場合、TX は、それらの演算子の対象となる型の組み合わせのセット内で最も外側の型になります。Otherwise, if any of the operators in U convert to types that are encompassed by T, then TX is the most encompassing type in the combined set of target types of those operators. 最も外側の型が1つだけ見つからない場合、変換はあいまいで、コンパイル時エラーが発生します。If exactly one most encompassing type cannot be found, then the conversion is ambiguous and a compile-time error occurs.
    • それ以外の場合、TX は、U内の演算子の対象となる型の組み合わせで最も包含される型です。Otherwise, TX is the most encompassed type in the combined set of target types of the operators in U. 最も包含されていない型が見つからない場合は、変換があいまいになり、コンパイル時エラーが発生します。If no most encompassed type can be found, then the conversion is ambiguous and a compile-time error occurs.
  • 最も具体的な変換演算子を見つけます。Find the most specific conversion operator:
    • SX から TXに変換するユーザー定義の変換演算子を1つだけ含む U 場合は、これが最も具体的な変換演算子です。If U contains exactly one user-defined conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • それ以外の U 場合、SX から TXに変換するリフト変換演算子が1つだけ含まれている場合は、これが最も具体的な変換演算子になります。Otherwise, if U contains exactly one lifted conversion operator that converts from SX to TX, then this is the most specific conversion operator.
    • それ以外の場合、変換はあいまいで、コンパイル時エラーが発生します。Otherwise, the conversion is ambiguous and a compile-time error occurs.
  • 最後に、変換を適用します。Finally, apply the conversion:
    • SSXない場合は、S から SX への標準の明示的な変換が実行されます。If S is not SX, then a standard explicit conversion from S to SX is performed.
    • SX から TXに変換するために、ユーザー定義の最も限定的な変換演算子が呼び出されます。The most specific user-defined conversion operator is invoked to convert from SX to TX.
    • TXTない場合は、TX から T への標準の明示的な変換が実行されます。If TX is not T, then a standard explicit conversion from TX to T is performed.

匿名関数の変換Anonymous function conversions

Anonymous_method_expressionまたはlambda_expressionは、匿名関数 (匿名関数式) として分類されます。An anonymous_method_expression or lambda_expression is classified as an anonymous function (Anonymous function expressions). 式に型がありませんが、互換性のあるデリゲート型または式ツリー型に暗黙的に変換できます。The expression does not have a type but can be implicitly converted to a compatible delegate type or expression tree type. 具体的には、匿名関数 F は、指定された D デリゲート型と互換性があります。Specifically, an anonymous function F is compatible with a delegate type D provided:

  • Fanonymous_function_signatureが含まれている場合は、DF のパラメーターの数が同じになります。If F contains an anonymous_function_signature, then D and F have the same number of parameters.
  • Fanonymous_function_signatureが含まれていない場合、D のパラメーターに out parameter 修飾子が指定されていない限り、D には任意の型の0個以上のパラメーターを含めることができます。If F does not contain an anonymous_function_signature, then D may have zero or more parameters of any type, as long as no parameter of D has the out parameter modifier.
  • F に明示的に型指定されたパラメーターリストがある場合、D 内の各パラメーターの型と修飾子は F内の対応するパラメーターと同じになります。If F has an explicitly typed parameter list, each parameter in D has the same type and modifiers as the corresponding parameter in F.
  • F に暗黙的に型指定されたパラメーターリストがある場合、D には ref または out パラメーターがありません。If F has an implicitly typed parameter list, D has no ref or out parameters.
  • F の本体が式であり、Dvoid の戻り値の型であるか、または F が非同期であり、D の戻り値の型が Taskである場合、F の本体は、D( 式ステートメント) として許可される有効な式 (wrt) になります。If the body of F is an expression, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt Expressions) that would be permitted as a statement_expression (Expression statements).
  • F の本体がステートメントブロックであり、Dvoid の戻り値の型を持っている場合、または F が非同期で、D の戻り値の型が Taskの場合、F の本体は有効なステートメントブロック (wrt block) で、Dステートメントで式が指定されていません。If the body of F is a statement block, and either D has a void return type or F is async and D has the return type Task, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid statement block (wrt Blocks) in which no return statement specifies an expression.
  • F の本体が式であり F非同期ではなく、D の戻り値の T型が void でない場合、またはF が async で、D が戻り値の型 Task<T>の場合、F の本体は、暗黙的に Dに変換できる有効な式 (wrt) になります。If the body of F is an expression, and either F is non-async and D has a non-void return type T, or F is async and D has a return type Task<T>, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid expression (wrt Expressions) that is implicitly convertible to T.
  • F の本体がステートメントブロックで、F が非同期ではなくD が void 以外の戻り値の型 Tの場合、またはF が async で D が戻り値の型 Task<T>である場合、F の各パラメーターに Dの対応するパラメーターの型が指定されている場合、F の本体は到達できないエンドポイントを持つ有効なステートメントブロック (wrt block) です。この場合、各 return ステートメントは、暗黙的に変換可能な式を指定します。If the body of F is a statement block, and either F is non-async and D has a non-void return type T, or F is async and D has a return type Task<T>, then when each parameter of F is given the type of the corresponding parameter in D, the body of F is a valid statement block (wrt Blocks) with a non-reachable end point in which each return statement specifies an expression that is implicitly convertible to T.

簡潔にするために、このセクションでは、タスクの種類 Task および Task<T> (非同期関数) に短い形式を使用します。For the purpose of brevity, this section uses the short form for the task types Task and Task<T> (Async functions).

ラムダ式 F は、F がデリゲート型 Dと互換性がある場合に Expression<D> 式ツリー型と互換性があります。A lambda expression F is compatible with an expression tree type Expression<D> if F is compatible with the delegate type D. これは匿名メソッドには適用されず、ラムダ式にのみ適用されることに注意してください。Note that this does not apply to anonymous methods, only lambda expressions.

特定のラムダ式は、式のツリー型に変換できません。変換が存在する場合でも、コンパイル時に失敗します。Certain lambda expressions cannot be converted to expression tree types: Even though the conversion exists, it fails at compile-time. ラムダ式の場合は、次のようになります。This is the case if the lambda expression:

  • ブロック本体があるHas a block body
  • 単純型または複合型の代入演算子を含んでいますContains simple or compound assignment operators
  • 動的にバインドされた式を含むContains a dynamically bound expression
  • 非同期Is async

次の例では、汎用デリゲート Func<A,R> 型を使用します。これは、型 A の引数を受け取り、R型の値を返す関数を表します。The examples that follow use a generic delegate type Func<A,R> which represents a function that takes an argument of type A and returns a value of type R:

delegate R Func<A,R>(A arg);

割り当てIn the assignments

Func<int,int> f1 = x => x + 1;                 // Ok

Func<int,double> f2 = x => x + 1;              // Ok

Func<double,int> f3 = x => x + 1;              // Error

Func<int, Task<int>> f4 = async x => x + 1;    // Ok

各匿名関数のパラメーターと戻り値の型は、匿名関数が割り当てられている変数の型によって決まります。the parameter and return types of each anonymous function are determined from the type of the variable to which the anonymous function is assigned.

最初の代入は、匿名関数をデリゲート Func<int,int> 型に正常に変換します。これは、x に型 intが指定されている場合、x+1 は型 intに暗黙的に変換できる有効な式であるためです。The first assignment successfully converts the anonymous function to the delegate type Func<int,int> because, when x is given type int, x+1 is a valid expression that is implicitly convertible to type int.

同様に、2番目の代入は、匿名関数をデリゲート Func<int,double> 型に正常に変換します。これは、x+1 (型 int) の結果が暗黙的に型 doubleに変換可能であるためです。Likewise, the second assignment successfully converts the anonymous function to the delegate type Func<int,double> because the result of x+1 (of type int) is implicitly convertible to type double.

ただし、3番目の代入はコンパイル時エラーになります。これは、x に型 doubleが指定されている場合、x+1 (型 double) の結果が型 intに暗黙的に変換可能ではないためです。However, the third assignment is a compile-time error because, when x is given type double, the result of x+1 (of type double) is not implicitly convertible to type int.

4番目の代入は、匿名の非同期関数をデリゲート型 Func<int, Task<int>> に正常に変換します。これは、x+1 (型 int) の結果が、タスクの種類 Task<int>int 結果の型に暗黙的に変換できるためです。The fourth assignment successfully converts the anonymous async function to the delegate type Func<int, Task<int>> because the result of x+1 (of type int) is implicitly convertible to the result type int of the task type Task<int>.

匿名関数は、オーバーロードの解決に影響を与える可能性があり、型の推定に関与します。Anonymous functions may influence overload resolution, and participate in type inference. 詳細については、「関数メンバー 」を参照してください。See Function members for further details.

デリゲート型への匿名関数変換の評価Evaluation of anonymous function conversions to delegate types

匿名関数をデリゲート型に変換すると、匿名関数を参照するデリゲートインスタンスと、評価時にアクティブであるキャプチャされた外部変数の (空の場合もありますが) セットが生成されます。Conversion of an anonymous function to a delegate type produces a delegate instance which references the anonymous function and the (possibly empty) set of captured outer variables that are active at the time of the evaluation. デリゲートが呼び出されると、匿名関数の本体が実行されます。When the delegate is invoked, the body of the anonymous function is executed. 本文内のコードは、デリゲートによって参照されるキャプチャされた外部変数のセットを使用して実行されます。The code in the body is executed using the set of captured outer variables referenced by the delegate.

匿名関数から生成されたデリゲートの呼び出しリストには、1つのエントリが含まれます。The invocation list of a delegate produced from an anonymous function contains a single entry. デリゲートの正確なターゲットオブジェクトとターゲットメソッドは指定されていません。The exact target object and target method of the delegate are unspecified. 特に、デリゲートのターゲットオブジェクトが null、外側の関数メンバーの this 値、またはその他のオブジェクトであるかどうかは指定されていません。In particular, it is unspecified whether the target object of the delegate is null, the this value of the enclosing function member, or some other object.

同じ (場合によっては空の) キャプチャされた外部変数インスタンスを同じデリゲート型に対して同じ匿名関数から変換すると、同じデリゲートインスタンスを返すことができます (ただし、必須ではありません)。Conversions of semantically identical anonymous functions with the same (possibly empty) set of captured outer variable instances to the same delegate types are permitted (but not required) to return the same delegate instance. ここでは、意味的に同じ用語が使用されています。これは、匿名関数の実行によって、同じ引数を指定した場合と同じ効果が生成されることを意味します。The term semantically identical is used here to mean that execution of the anonymous functions will, in all cases, produce the same effects given the same arguments. この規則は、次のようなコードを最適化することを許可します。This rule permits code such as the following to be optimized.

delegate double Function(double x);

class Test
{
    static double[] Apply(double[] a, Function f) {
        double[] result = new double[a.Length];
        for (int i = 0; i < a.Length; i++) result[i] = f(a[i]);
        return result;
    }

    static void F(double[] a, double[] b) {
        a = Apply(a, (double x) => Math.Sin(x));
        b = Apply(b, (double y) => Math.Sin(y));
        ...
    }
}

2つの匿名関数デリゲートは、キャプチャされた外部変数と同じ (空の) セットを持つため、匿名関数は意味が同じであるため、コンパイラはデリゲートが同じターゲットメソッドを参照することを許可します。Since the two anonymous function delegates have the same (empty) set of captured outer variables, and since the anonymous functions are semantically identical, the compiler is permitted to have the delegates refer to the same target method. 実際には、コンパイラは、両方の匿名関数式からまったく同じデリゲートインスタンスを返すことができます。Indeed, the compiler is permitted to return the very same delegate instance from both anonymous function expressions.

式ツリー型への匿名関数変換の評価Evaluation of anonymous function conversions to expression tree types

匿名関数から式ツリー型への変換では、式ツリー (式ツリー型) が生成されます。Conversion of an anonymous function to an expression tree type produces an expression tree (Expression tree types). より正確には、匿名関数の変換を評価すると、匿名関数自体の構造を表すオブジェクト構造の構築につながります。More precisely, evaluation of the anonymous function conversion leads to the construction of an object structure that represents the structure of the anonymous function itself. 式ツリーの正確な構造と、それを作成するための正確なプロセスは、実装が定義されています。The precise structure of the expression tree, as well as the exact process for creating it, are implementation defined.

実装例Implementation example

このセクションでは、他C#の構造体の観点から、匿名関数の変換を実装する方法について説明します。This section describes a possible implementation of anonymous function conversions in terms of other C# constructs. ここで説明する実装は、Microsoft C#コンパイラで使用されているのと同じ原則に基づいていますが、必須の実装ではなく、可能な唯一の方法でもあります。The implementation described here is based on the same principles used by the Microsoft C# compiler, but it is by no means a mandated implementation, nor is it the only one possible. ここでは、式ツリーへの変換について簡単に説明します。正確なセマンティクスは、この仕様の範囲外です。It only briefly mentions conversions to expression trees, as their exact semantics are outside the scope of this specification.

このセクションの残りの部分では、さまざまな特性を持つ匿名関数を含むコードの例をいくつか示します。The remainder of this section gives several examples of code that contains anonymous functions with different characteristics. 各例では、他のC#コンストラクトのみを使用するコードへの対応する変換が提供されています。For each example, a corresponding translation to code that uses only other C# constructs is provided. この例では、識別子 D は、次のデリゲート型を表すことによって想定されています。In the examples, the identifier D is assumed by represent the following delegate type:

public delegate void D();

匿名関数の最も単純な形式は、外部変数をキャプチャする関数です。The simplest form of an anonymous function is one that captures no outer variables:

class Test
{
    static void F() {
        D d = () => { Console.WriteLine("test"); };
    }
}

これは、匿名関数のコードが配置される、コンパイラによって生成された静的メソッドを参照するデリゲートのインスタンス化に変換できます。This can be translated to a delegate instantiation that references a compiler generated static method in which the code of the anonymous function is placed:

class Test
{
    static void F() {
        D d = new D(__Method1);
    }

    static void __Method1() {
        Console.WriteLine("test");
    }
}

次の例では、匿名関数は thisのインスタンスメンバーを参照します。In the following example, the anonymous function references instance members of this:

class Test
{
    int x;

    void F() {
        D d = () => { Console.WriteLine(x); };
    }
}

これは、匿名関数のコードを含む、コンパイラによって生成されるインスタンスメソッドに変換できます。This can be translated to a compiler generated instance method containing the code of the anonymous function:

class Test
{
    int x;

    void F() {
        D d = new D(__Method1);
    }

    void __Method1() {
        Console.WriteLine(x);
    }
}

この例では、匿名関数はローカル変数をキャプチャします。In this example, the anonymous function captures a local variable:

class Test
{
    void F() {
        int y = 123;
        D d = () => { Console.WriteLine(y); };
    }
}

ローカル変数の有効期間は、少なくとも匿名関数デリゲートの有効期間に拡張する必要があります。The lifetime of the local variable must now be extended to at least the lifetime of the anonymous function delegate. これは、コンパイラによって生成されるクラスのフィールドにローカル変数を "hoisting" することによって実現できます。This can be achieved by "hoisting" the local variable into a field of a compiler generated class. ローカル変数 (ローカル変数のインスタンス化) のインスタンス化は、コンパイラによって生成されたクラスのインスタンスの作成に対応し、ローカル変数へのアクセスは、コンパイラによって生成されるクラスのインスタンス内のフィールドへのアクセスに対応します。Instantiation of the local variable (Instantiation of local variables) then corresponds to creating an instance of the compiler generated class, and accessing the local variable corresponds to accessing a field in the instance of the compiler generated class. さらに、匿名関数は、コンパイラによって生成されるクラスのインスタンスメソッドになります。Furthermore, the anonymous function becomes an instance method of the compiler generated class:

class Test
{
    void F() {
        __Locals1 __locals1 = new __Locals1();
        __locals1.y = 123;
        D d = new D(__locals1.__Method1);
    }

    class __Locals1
    {
        public int y;

        public void __Method1() {
            Console.WriteLine(y);
        }
    }
}

最後に、次の匿名関数は、this、および有効期間が異なる2つのローカル変数をキャプチャします。Finally, the following anonymous function captures this as well as two local variables with different lifetimes:

class Test
{
    int x;

    void F() {
        int y = 123;
        for (int i = 0; i < 10; i++) {
            int z = i * 2;
            D d = () => { Console.WriteLine(x + y + z); };
        }
    }
}

ここでは、別のブロックのローカル変数が独立した有効期間を持つことができるように、ローカルがキャプチャされた各ステートメントブロックに対して、コンパイラによって生成されるクラスが作成されます。Here, a compiler generated class is created for each statement block in which locals are captured such that the locals in the different blocks can have independent lifetimes. __Locals2のインスタンス (内部ステートメントブロックに対してコンパイラによって生成されるクラス) には、ローカル変数 z__Locals1のインスタンスを参照するフィールドが含まれています。An instance of __Locals2, the compiler generated class for the inner statement block, contains the local variable z and a field that references an instance of __Locals1. __Locals1のインスタンス (外側のステートメントブロックに対してコンパイラによって生成されるクラス) には、ローカル変数 y と、外側の関数メンバーの this を参照するフィールドが含まれています。An instance of __Locals1, the compiler generated class for the outer statement block, contains the local variable y and a field that references this of the enclosing function member. これらのデータ構造を使用すると、__Local2のインスタンスを介してキャプチャされたすべての外部変数にアクセスできます。そのため、匿名関数のコードは、そのクラスのインスタンスメソッドとして実装できます。With these data structures it is possible to reach all captured outer variables through an instance of __Local2, and the code of the anonymous function can thus be implemented as an instance method of that class.

class Test
{
    void F() {
        __Locals1 __locals1 = new __Locals1();
        __locals1.__this = this;
        __locals1.y = 123;
        for (int i = 0; i < 10; i++) {
            __Locals2 __locals2 = new __Locals2();
            __locals2.__locals1 = __locals1;
            __locals2.z = i * 2;
            D d = new D(__locals2.__Method1);
        }
    }

    class __Locals1
    {
        public Test __this;
        public int y;
    }

    class __Locals2
    {
        public __Locals1 __locals1;
        public int z;

        public void __Method1() {
            Console.WriteLine(__locals1.__this.x + __locals1.y + z);
        }
    }
}

ここでは、ローカル変数をキャプチャするために使用するのと同じ手法を、匿名関数を式ツリーに変換するときにも使用できます。コンパイラによって生成されたオブジェクトへの参照は式ツリーに格納でき、ローカル変数へのアクセスは次のようになります。これらのオブジェクトに対するフィールドアクセスとして表されます。The same technique applied here to capture local variables can also be used when converting anonymous functions to expression trees: References to the compiler generated objects can be stored in the expression tree, and access to the local variables can be represented as field accesses on these objects. この方法の利点は、"リフトされた" ローカル変数をデリゲートと式ツリーの間で共有できることです。The advantage of this approach is that it allows the "lifted" local variables to be shared between delegates and expression trees.

メソッドグループの変換Method group conversions

メソッドグループ (式の分類) から互換性のあるデリゲート型への暗黙の変換 (暗黙の変換) が存在します。An implicit conversion (Implicit conversions) exists from a method group (Expression classifications) to a compatible delegate type. デリゲート型 D と、メソッドグループとして分類される式 E が指定されている場合、次に示すように、E のパラメーターの型と修飾子を使用して構築された引数リストに、Dが通常の形式 (適用可能な関数メンバー) に適用可能なメソッドが少なくとも1つ含まれている場合は、D E からGiven a delegate type D and an expression E that is classified as a method group, an implicit conversion exists from E to D if E contains at least one method that is applicable in its normal form (Applicable function member) to an argument list constructed by use of the parameter types and modifiers of D, as described in the following.

メソッドグループからデリゲート D 型への変換のコンパイル時アプリケーション E については、次の説明を参照してください。The compile-time application of a conversion from a method group E to a delegate type D is described in the following. E から D への暗黙的な変換が存在しても、変換のコンパイル時のアプリケーションがエラーなしで成功するとは限りません。Note that the existence of an implicit conversion from E to D does not guarantee that the compile-time application of the conversion will succeed without error.

  • フォーム E(A)のメソッド呼び出し (メソッドの呼び出し) に対応する1つのメソッド M が選択されていますが、次のように変更されています。A single method M is selected corresponding to a method invocation (Method invocations) of the form E(A), with the following modifications:
    • 引数リスト A は式のリストであり、それぞれが変数として分類され、Dformal_parameter_list内の対応するパラメーターの型と修飾子 (ref または out) を使用します。The argument list A is a list of expressions, each classified as a variable and with the type and modifier (ref or out) of the corresponding parameter in the formal_parameter_list of D.
    • 考慮される候補メソッドは、通常の形式 (適用可能な関数メンバー) で適用可能なメソッドのみであり、拡張フォームにのみ適用されるものではありません。The candidate methods considered are only those methods that are applicable in their normal form (Applicable function member), not those applicable only in their expanded form.
  • メソッド呼び出しのアルゴリズムによってエラーが発生した場合、コンパイル時エラーが発生します。If the algorithm of Method invocations produces an error, then a compile-time error occurs. それ以外の場合、D と同じ数のパラメーターを持ち、変換が存在していると見なされる M、1つの最適なメソッドが生成されます。Otherwise the algorithm produces a single best method M having the same number of parameters as D and the conversion is considered to exist.
  • 選択されたメソッド M は、デリゲート型 Dと互換性がある (デリゲート互換性) 必要があります。そうでない場合は、コンパイル時エラーが発生します。The selected method M must be compatible (Delegate compatibility) with the delegate type D, or otherwise, a compile-time error occurs.
  • 選択したメソッド M がインスタンスメソッドの場合、E に関連付けられたインスタンス式によって、デリゲートのターゲットオブジェクトが決定されます。If the selected method M is an instance method, the instance expression associated with E determines the target object of the delegate.
  • 選択したメソッド M が、インスタンス式でのメンバーアクセスによって示される拡張メソッドである場合、そのインスタンス式によって、デリゲートのターゲットオブジェクトが決定されます。If the selected method M is an extension method which is denoted by means of a member access on an instance expression, that instance expression determines the target object of the delegate.
  • 変換の結果は D型の値になります。つまり、選択したメソッドとターゲットオブジェクトを参照する新しく作成されたデリゲートです。The result of the conversion is a value of type D, namely a newly created delegate that refers to the selected method and target object.
  • メソッド呼び出しのアルゴリズムがインスタンスメソッドを検出できず、拡張メソッドの呼び出し (拡張メソッドの呼び出し) として E(A) の呼び出しの処理に成功する場合は、このプロセスによって、拡張メソッドへのデリゲートの作成につながる可能性があることに注意してください。Note that this process can lead to the creation of a delegate to an extension method, if the algorithm of Method invocations fails to find an instance method but succeeds in processing the invocation of E(A) as an extension method invocation (Extension method invocations). このように作成されたデリゲートは、拡張メソッドとその最初の引数をキャプチャします。A delegate thus created captures the extension method as well as its first argument.

次の例は、メソッドグループの変換を示しています。The following example demonstrates method group conversions:

delegate string D1(object o);

delegate object D2(string s);

delegate object D3();

delegate string D4(object o, params object[] a);

delegate string D5(int i);

class Test
{
    static string F(object o) {...}

    static void G() {
        D1 d1 = F;            // Ok
        D2 d2 = F;            // Ok
        D3 d3 = F;            // Error -- not applicable
        D4 d4 = F;            // Error -- not applicable in normal form
        D5 d5 = F;            // Error -- applicable but not compatible

    }
}

d1 への代入は、メソッドグループ FD1型の値に暗黙的に変換します。The assignment to d1 implicitly converts the method group F to a value of type D1.

d2 への代入は、弱い派生型 (反変) のパラメーター型と、より派生した (共変の) 戻り値の型を持つメソッドへのデリゲートを作成する方法を示しています。The assignment to d2 shows how it is possible to create a delegate to a method that has less derived (contravariant) parameter types and a more derived (covariant) return type.

d3 への代入は、メソッドが適用されない場合に変換が存在しないことを示します。The assignment to d3 shows how no conversion exists if the method is not applicable.

d4 への割り当ては、メソッドを通常の形式で適用する方法を示しています。The assignment to d4 shows how the method must be applicable in its normal form.

d5 への代入は、デリゲートとメソッドのパラメーターと戻り値の型が参照型に対してのみ異なることを許可する方法を示しています。The assignment to d5 shows how parameter and return types of the delegate and method are allowed to differ only for reference types.

他の暗黙的な変換および明示的な変換と同様に、cast 演算子を使用してメソッドグループの変換を明示的に実行できます。As with all other implicit and explicit conversions, the cast operator can be used to explicitly perform a method group conversion. この例では、Thus, the example

object obj = new EventHandler(myDialog.OkClick);

書き込みが可能could instead be written

object obj = (EventHandler)myDialog.OkClick;

メソッドグループは、オーバーロードの解決に影響を与える可能性があり、型の推定に関与します。Method groups may influence overload resolution, and participate in type inference. 詳細については、「関数メンバー 」を参照してください。See Function members for further details.

メソッドグループの変換の実行時の評価は、次のように行われます。The run-time evaluation of a method group conversion proceeds as follows:

  • コンパイル時に選択されたメソッドがインスタンスメソッドである場合、またはインスタンスメソッドとしてアクセスされる拡張メソッドである場合は、デリゲートのターゲットオブジェクトは Eに関連付けられたインスタンス式から決定されます。If the method selected at compile-time is an instance method, or it is an extension method which is accessed as an instance method, the target object of the delegate is determined from the instance expression associated with E:
    • インスタンス式が評価されます。The instance expression is evaluated. この評価によって例外が発生した場合、それ以上の手順は実行されません。If this evaluation causes an exception, no further steps are executed.
    • インスタンス式がreference_typeの場合、インスタンス式によって計算された値が対象オブジェクトになります。If the instance expression is of a reference_type, the value computed by the instance expression becomes the target object. 選択したメソッドがインスタンスメソッドで、ターゲットオブジェクトが null場合、System.NullReferenceException がスローされ、それ以上の手順は実行されません。If the selected method is an instance method and the target object is null, a System.NullReferenceException is thrown and no further steps are executed.
    • インスタンス式がvalue_typeの場合は、値をオブジェクトに変換するボックス化操作 (ボックス化変換) が実行され、このオブジェクトが対象オブジェクトになります。If the instance expression is of a value_type, a boxing operation (Boxing conversions) is performed to convert the value to an object, and this object becomes the target object.
  • それ以外の場合は、選択したメソッドが静的メソッド呼び出しの一部になり、デリゲートのターゲットオブジェクトが nullされます。Otherwise the selected method is part of a static method call, and the target object of the delegate is null.
  • 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.
  • 新しいデリゲートインスタンスは、コンパイル時に決定されたメソッドへの参照と、上記で計算されたターゲットオブジェクトへの参照を使用して初期化されます。The new delegate instance is initialized with a reference to the method that was determined at compile-time and a reference to the target object computed above.