変換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.
変換のために、型 object
と dynamic
は同等と見なされます。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.
object
とdynamic
は同等と見なされるため、object
とdynamic
間の id 変換と、dynamic
のすべての出現箇所をobject
に置き換える場合の構築された型の間の id 変換があります。Becauseobject
anddynamic
are considered equivalent there is an identity conversion betweenobject
anddynamic
, and between constructed types that are the same when replacing all occurrences ofdynamic
withobject
.
暗黙の数値変換Implicit numeric conversions
暗黙的な数値変換は次のとおりです。The implicit numeric conversions are:
sbyte
からshort
、int
、long
、float
、double
、decimal
になります。Fromsbyte
toshort
,int
,long
,float
,double
, ordecimal
.byte
からshort
、ushort
、int
、uint
、long
、ulong
、float
、double
、decimal
になります。Frombyte
toshort
,ushort
,int
,uint
,long
,ulong
,float
,double
, ordecimal
.short
からint
、long
、float
、double
、decimal
になります。Fromshort
toint
,long
,float
,double
, ordecimal
.ushort
からint
、uint
、long
、ulong
、float
、double
、decimal
になります。Fromushort
toint
,uint
,long
,ulong
,float
,double
, ordecimal
.int
からlong
、float
、double
、またはdecimal
になります。Fromint
tolong
,float
,double
, ordecimal
.uint
からlong
、ulong
、float
、double
、decimal
になります。Fromuint
tolong
,ulong
,float
,double
, ordecimal
.long
からfloat
、double
、またはdecimal
。Fromlong
tofloat
,double
, ordecimal
.ulong
からfloat
、double
、またはdecimal
。Fromulong
tofloat
,double
, ordecimal
.char
からushort
、int
、uint
、long
、ulong
、float
、double
、decimal
になります。Fromchar
toushort
,int
,uint
,long
,ulong
,float
,double
, ordecimal
.float
からdouble
。Fromfloat
todouble
.
int
、uint
、long
、または 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 許容の変換が存在します。 S
For 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 fromS?
toT?
.S
からT?
への暗黙的な変換です。An implicit conversion fromS
toT?
.
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 fromS?
toT?
:- ソース値が null (
HasValue
プロパティが false) の場合、結果はT?
型の null 値になります。If the source value is null (HasValue
property is false), the result is the null value of typeT?
. - それ以外の場合、変換は
S?
からS
へのラップ解除として評価された後、S
からT
への基になる変換と、T
からT?
へのラップ (Null 許容型) が行われます。Otherwise, the conversion is evaluated as an unwrapping fromS?
toS
, followed by the underlying conversion fromS
toT
, followed by a wrapping (Nullable types) fromT
toT?
.
- ソース値が null (
Null 許容型変換が
S
からT?
に対して行われる場合、変換はS
からT
の基になる変換として評価され、その後、T
からT?
へのラップが行われます。If the nullable conversion is fromS
toT?
, the conversion is evaluated as the underlying conversion fromS
toT
followed by a wrapping fromT
toT?
.
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 toobject
anddynamic
. - 任意のclass_type
S
から任意のclass_typeT
へのS
は、T
から派生しています。From any class_typeS
to any class_typeT
, providedS
is derived fromT
. - 任意のclass_type
S
から、S
がT
を実装しているinterface_typeT
。From any class_typeS
to any interface_typeT
, providedS
implementsT
. - 任意のinterface_type
S
から任意のinterface_typeT
へのS
は、T
から派生しています。From any interface_typeS
to any interface_typeT
, providedS
is derived fromT
. - 要素型が
T
のarray_typeS
から、次のすべてが満たされていれば、要素型がTE
のarray_typeにSE
ます。From an array_typeS
with an element typeSE
to an array_typeT
with an element typeTE
, provided all of the following are true:S
とT
は要素の型のみが異なります。S
andT
differ only in element type. 言い換えると、S
とT
の次元数が同じになります。In other words,S
andT
have the same number of dimensions.SE
とTE
は両方ともreference_typeです。BothSE
andTE
are reference_types.SE
からTE
への暗黙的な参照変換が存在します。An implicit reference conversion exists fromSE
toTE
.
- 任意のarray_typeから
System.Array
とそれが実装するインターフェイス。From any array_type toSystem.Array
and the interfaces it implements. S
からT
への暗黙的な id または参照の変換がある場合は、1次元配列型からSystem.Collections.Generic.IList<T>
とその基本インターフェイスをS[]
します。From a single-dimensional array typeS[]
toSystem.Collections.Generic.IList<T>
and its base interfaces, provided that there is an implicit identity or reference conversion fromS
toT
.- 任意のdelegate_typeから
System.Delegate
とそれが実装するインターフェイス。From any delegate_type toSystem.Delegate
and the interfaces it implements. - Null リテラルから任意のreference_typeにします。From the null literal to any reference_type.
- Reference_type
T0
への暗黙的な id または参照の変換がある場合は、任意のreference_typeからreference_typeT
、T0
にはT
への id 変換が含まれています。From any reference_type to a reference_typeT
if it has an implicit identity or reference conversion to a reference_typeT0
andT0
has an identity conversion toT
. - インターフェイスまたはデリゲート型への暗黙的な id または参照の変換がある場合は、任意のreference_typeからインターフェイスまたはデリゲート型に
T
、T0
およびT0
がT
への分散変換可能 (変位変換) になります。From any reference_type to an interface or delegate typeT
if it has an implicit identity or reference conversion to an interface or delegate typeT0
andT0
is variance-convertible (Variance conversion) toT
. - 参照型として認識されている型パラメーターを使用する暗黙的な変換。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から object
と dynamic
に、 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_typeは System.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
インターフェイス型へのボックス変換があり、I0
は I
への変位変換 (変位変換) があります。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 boxedT
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
s2
と i
の割り当てには、暗黙的な動的変換が使用されます。この場合、操作のバインドは実行時まで中断されます。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
の値が変換先の型の範囲内にある場合に、型sbyte
、byte
、ushort
、uint
、ulong
、または constant_expression に変換できます。A constant_expression (Constant expressions) of typeint
can be converted to typesbyte
,byte
,short
,ushort
,uint
, orulong
, provided the value of the constant_expression is within the range of the destination type.- Constant_expressionの値が負でない場合は、型
long
のconstant_expressionをulong
型に変換できます。A constant_expression of typelong
can be converted to typeulong
, 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
から、有効な基本クラスC
、T
からC
の任意の基底クラス、T
によって実装されている任意のインターフェイスにC
ます。FromT
to its effective base classC
, fromT
to any base class ofC
, and fromT
to any interface implemented byC
. 実行時にT
が値型の場合、変換はボックス化変換として実行されます。At run-time, ifT
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
の任意の基本インターフェイスになります。FromT
to an interface typeI
inT
's effective interface set and fromT
to any base interface ofI
. 実行時にT
が値型の場合、変換はボックス化変換として実行されます。At run-time, ifT
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
には、T
がU
(型パラメーターの制約) に依存しています。FromT
to a type parameterU
, providedT
depends onU
(Type parameter constraints). 実行時にU
が値型の場合、T
とU
は必ず同じ型であり、変換は実行されません。At run-time, ifU
is a value type, thenT
andU
are necessarily the same type and no conversion is performed. それ以外の場合、T
が値型の場合、変換はボックス化変換として実行されます。Otherwise, ifT
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 toT
, providedT
is known to be a reference type. - 参照型への暗黙的な変換が含まれている場合、
T
から参照型への変換がI
場合S0
およびS0
にはS
への id 変換が含まれます。FromT
to a reference typeI
if it has an implicit conversion to a reference typeS0
andS0
has an identity conversion toS
. 実行時には、S0
への変換と同じ方法で変換が実行されます。At run-time the conversion is executed the same way as the conversion toS0
. - インターフェイス型またはデリゲート
I0
型への暗黙的な変換が含まれている場合は、T
からインターフェイス型にI
します。また、I0
はI
(変位変換) に変換可能です。FromT
to an interface typeI
if it has an implicit conversion to an interface or delegate typeI0
andI0
is variance-convertible toI
(Variance conversion). 実行時にT
が値型の場合、変換はボックス化変換として実行されます。At run-time, ifT
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
からbyte
、ushort
、uint
、ulong
、char
になります。Fromsbyte
tobyte
,ushort
,uint
,ulong
, orchar
.byte
からsbyte
とchar
になります。Frombyte
tosbyte
andchar
.short
からsbyte
、byte
、ushort
、uint
、ulong
、char
になります。Fromshort
tosbyte
,byte
,ushort
,uint
,ulong
, orchar
.ushort
からsbyte
、byte
、short
、またはchar
になります。Fromushort
tosbyte
,byte
,short
, orchar
.int
からsbyte
、byte
、short
、ushort
、uint
、ulong
、char
になります。Fromint
tosbyte
,byte
,short
,ushort
,uint
,ulong
, orchar
.uint
からsbyte
、byte
、short
、ushort
、int
、char
になります。Fromuint
tosbyte
,byte
,short
,ushort
,int
, orchar
.long
からsbyte
、byte
、short
、ushort
、int
、uint
、ulong
、char
になります。Fromlong
tosbyte
,byte
,short
,ushort
,int
,uint
,ulong
, orchar
.ulong
からsbyte
、byte
、short
、ushort
、int
、uint
、long
、char
になります。Fromulong
tosbyte
,byte
,short
,ushort
,int
,uint
,long
, orchar
.char
からsbyte
、byte
、またはshort
。Fromchar
tosbyte
,byte
, orshort
.float
からsbyte
、byte
、short
、ushort
、int
、uint
、long
、ulong
、char
、decimal
になります。Fromfloat
tosbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
, ordecimal
.double
からsbyte
、byte
、short
、ushort
、int
、uint
、long
、ulong
、char
、float
、decimal
になります。Fromdouble
tosbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
, ordecimal
.decimal
からsbyte
、byte
、short
、ushort
、int
、uint
、long
、ulong
、char
、float
、double
になります。Fromdecimal
tosbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
, ordouble
.
明示的な変換には暗黙的な数値変換と明示的な数値変換がすべて含まれているため、キャスト式 (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 achecked
context, the conversion succeeds if the value of the source operand is within the range of the destination type, but throws aSystem.OverflowException
if the value of the source operand is outside the range of the destination type.unchecked
のコンテキストでは、変換は常に成功し、次のように進行します。In anunchecked
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 fromdecimal
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, aSystem.OverflowException
is thrown.float
またはdouble
から整数型への変換の場合、処理は、変換が行われるオーバーフローチェックコンテキスト (checked および unchecked 演算子) に依存します。For a conversion fromfloat
ordouble
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 achecked
context, the conversion proceeds as follows:- オペランドの値が NaN または無限の場合は、
System.OverflowException
がスローされます。If the value of the operand is NaN or infinite, aSystem.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, aSystem.OverflowException
is thrown.
- オペランドの値が NaN または無限の場合は、
unchecked
のコンテキストでは、変換は常に成功し、次のように進行します。In anunchecked
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 fromdouble
tofloat
, thedouble
value is rounded to the nearestfloat
value.double
値が小さすぎてfloat
として表現できない場合、結果は正のゼロまたは負のゼロになります。If thedouble
value is too small to represent as afloat
, the result becomes positive zero or negative zero.double
値が大きすぎてfloat
として表現できない場合、結果は正の無限大または負の無限大になります。If thedouble
value is too large to represent as afloat
, the result becomes positive infinity or negative infinity.double
値が NaN の場合、結果も NaN になります。If thedouble
value is NaN, the result is also NaN.float
またはdouble
からdecimal
への変換では、変換元の値がdecimal
表現に変換され、必要に応じて28進数の小数点以下の最も近い数値に丸められます (10 進数型)。For a conversion fromfloat
ordouble
todecimal
, the source value is converted todecimal
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 adecimal
, the result becomes zero. ソース値が NaN、無限大、または大きすぎてdecimal
として表すことができない場合は、System.OverflowException
がスローされます。If the source value is NaN, infinity, or too large to represent as adecimal
, aSystem.OverflowException
is thrown.decimal
からfloat
またはdouble
への変換では、decimal
値は最も近いdouble
またはfloat
値に丸められます。For a conversion fromdecimal
tofloat
ordouble
, thedecimal
value is rounded to the nearestdouble
orfloat
value. この変換によって精度が失われる場合がありますが、例外がスローされることはありません。While this conversion may lose precision, it never causes an exception to be thrown.
明示的な列挙変換Explicit enumeration conversions
明示的な列挙変換は次のとおりです。The explicit enumeration conversions are:
sbyte
、byte
、short
、ushort
、int
、uint
、long
、ulong
、char
、float
、double
、decimal
を任意のenum_typeにします。Fromsbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
,double
, ordecimal
to any enum_type.- 任意のenum_typeから
sbyte
、byte
、short
、ushort
、int
、uint
、long
、ulong
、char
、float
、double
、decimal
になります。From any enum_type tosbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
,double
, ordecimal
. - 任意のenum_typeから他のenum_typeに。From any enum_type to any other enum_type.
2つの型の間の明示的な列挙型変換は、参加しているenum_typeをenum_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. たとえば、および基になる型が int
のenum_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 fromS?
toT?
.S
からT?
への明示的な変換。An explicit conversion fromS
toT?
.S?
からT
への明示的な変換。An explicit conversion fromS?
toT
.
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 fromS?
toT?
:- ソース値が null (
HasValue
プロパティが false) の場合、結果はT?
型の null 値になります。If the source value is null (HasValue
property is false), the result is the null value of typeT?
. - それ以外の場合、変換は
S?
からS
へのラップ解除として評価された後、S
からT
への基になる変換と、その後にT
からT?
へのラップが行われます。Otherwise, the conversion is evaluated as an unwrapping fromS?
toS
, followed by the underlying conversion fromS
toT
, followed by a wrapping fromT
toT?
.
- ソース値が null (
- Null 許容型変換が
S
からT?
に対して行われる場合、変換はS
からT
の基になる変換として評価され、その後、T
からT?
へのラップが行われます。If the nullable conversion is fromS
toT?
, the conversion is evaluated as the underlying conversion fromS
toT
followed by a wrapping fromT
toT?
. - Null 許容型変換が
S?
からT
に対して行われる場合、変換はS?
からS
のラップ解除として評価され、その後にS
からT
への基になる変換が行われます。If the nullable conversion is fromS?
toT
, the conversion is evaluated as an unwrapping fromS?
toS
followed by the underlying conversion fromS
toT
.
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_typeにdynamic
します。Fromobject
anddynamic
to any other reference_type.- 任意のclass_type
S
から任意のclass_typeT
へのS
は、T
の基本クラスです。From any class_typeS
to any class_typeT
, providedS
is a base class ofT
. - 任意のclass_type
S
から任意のinterface_typeT
へのS
はシールされていませんが、S
は実装されていません。From any class_typeS
to any interface_typeT
, providedS
is not sealed and providedS
does not implementT
. - 任意のinterface_type
T
class_typeS
から、T
を実装T
がシールされていない、または指定されている場合は、S
を実装します。From any interface_typeS
to any class_typeT
, providedT
is not sealed or providedT
implementsS
. - 任意のinterface_type
S
から、S
はT
から派生したものではなく、任意のinterface_typeT
になります。From any interface_typeS
to any interface_typeT
, providedS
is not derived fromT
. - 要素型が
T
のarray_typeS
から、次のすべてが満たされていれば、要素型がTE
のarray_typeにSE
ます。From an array_typeS
with an element typeSE
to an array_typeT
with an element typeTE
, provided all of the following are true:S
とT
は要素の型のみが異なります。S
andT
differ only in element type. 言い換えると、S
とT
の次元数が同じになります。In other words,S
andT
have the same number of dimensions.SE
とTE
は両方ともreference_typeです。BothSE
andTE
are reference_types.SE
からTE
への明示的な参照変換が存在します。An explicit reference conversion exists fromSE
toTE
.
System.Array
と、それが実装するインターフェイスから、任意のarray_typeにします。FromSystem.Array
and the interfaces it implements to any array_type.S
からT
への明示的な参照変換がある場合は、1次元配列型からSystem.Collections.Generic.IList<T>
とその基本インターフェイスをS[]
します。From a single-dimensional array typeS[]
toSystem.Collections.Generic.IList<T>
and its base interfaces, provided that there is an explicit reference conversion fromS
toT
.S
からT
への明示的な id または参照の変換がある場合は、System.Collections.Generic.IList<S>
とその基本インターフェイスから、T[]
にします。FromSystem.Collections.Generic.IList<S>
and its base interfaces to a single-dimensional array typeT[]
, provided that there is an explicit identity or reference conversion fromS
toT
.System.Delegate
と、それが実装するインターフェイスから、任意のdelegate_typeにします。FromSystem.Delegate
and the interfaces it implements to any delegate_type.- 参照型から参照型への明示的な参照変換がある場合は
T
参照型から参照型への明示的な参照変換があり、T0
にはT
の id 変換がある場合はT0
。From a reference type to a reference typeT
if it has an explicit reference conversion to a reference typeT0
andT0
has an identity conversionT
. - 参照型からインターフェイスまたはデリゲート型への明示的な参照変換が含まれている場合
T
、その型がインターフェイスまたはデリゲートT0
型への明示的な参照変換を持っている場合、またはT0
がT
に変換可能であるかT
に変換可能かどうかを示します (分散変換)。From a reference type to an interface or delegate typeT
if it has an explicit reference conversion to an interface or delegate typeT0
and eitherT0
is variance-convertible toT
orT
is variance-convertible toT0
(Variance conversion). D<S1...Sn>
からD<T1...Tn>
D<X1...Xn>
が汎用デリゲート型である場合、D<S1...Sn>
はD<T1...Tn>
との互換性がないか、Xi
の型パラメーターD
ごとに次のようになります。FromD<S1...Sn>
toD<T1...Tn>
whereD<X1...Xn>
is a generic delegate type,D<S1...Sn>
is not compatible with or identical toD<T1...Tn>
, and for each type parameterXi
ofD
the following holds:Xi
が不変の場合、Si
はTi
と同じになります。IfXi
is invariant, thenSi
is identical toTi
.Xi
が共変の場合は、Si
からTi
への暗黙的または明示的な id または参照の変換が存在します。IfXi
is covariant, then there is an implicit or explicit identity or reference conversion fromSi
toTi
.Xi
が反変の場合、Si
とTi
は両方とも同じか、または両方の参照型になります。IfXi
is contravariant, thenSi
andTi
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. ボックス化解除変換は、型 object
、dynamic
および 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
型からのアンボックス変換があり、I0
が I
への 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
型からのアンボックス変換がある場合、または I0
が I
に対して分散変換可能であるか、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
の任意の基底クラスからT
にT
します。From the effective base classC
ofT
toT
and from any base class ofC
toT
. 実行時にT
が値型の場合、変換はボックス化解除変換として実行されます。At run-time, ifT
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 toT
. 実行時にT
が値型の場合、変換はボックス化解除変換として実行されます。At run-time, ifT
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_typeI
にT
ます。FromT
to any interface_typeI
provided there is not already an implicit conversion fromT
toI
. 実行時にT
が値型の場合、変換はボックス化変換として実行され、その後に明示的な参照変換が行われます。At run-time, ifT
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
は、T
がU
(型パラメーターの制約) に依存しています。From a type parameterU
toT
, providedT
depends onU
(Type parameter constraints). 実行時にU
が値型の場合、T
とU
は必ず同じ型であり、変換は実行されません。At run-time, ifU
is a value type, thenT
andU
are necessarily the same type and no conversion is performed. それ以外の場合、T
が値型の場合、変換はボックス化解除変換として実行されます。Otherwise, ifT
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)
を実行すると、ボックス化された int
を long
に直接変換できないため、例外がスローされます。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:
- Id 変換 (id 変換)Identity conversions (Identity conversion)
- 暗黙の数値変換 (暗黙的な数値変換)Implicit numeric conversions (Implicit numeric conversions)
- 暗黙の null 許容変換 (暗黙の null許容変換)Implicit nullable conversions (Implicit nullable conversions)
- 暗黙の参照変換 (暗黙的な参照変換)Implicit reference conversions (Implicit reference conversions)
- ボックス化変換 (ボックス化変換)Boxing conversions (Boxing conversions)
- 暗黙の定数式の変換 (暗黙の動的変換)Implicit constant expression conversions (Implicit dynamic conversions)
- 型パラメーターを含む暗黙の型変換 (型パラメーターを含む暗黙の型変換)Implicit conversions involving type parameters (Implicit conversions involving type parameters)
標準の暗黙の変換は、明示的にユーザー定義の暗黙的な変換を除外します。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 許容型である場合は、S0
と T0
がその基になる型を参照するようにします。それ以外の場合、S0
と T0
はそれぞれ S
と T
になります。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:
S0
とT0
の種類は異なります。S0
andT0
are different types.S0
またはT0
は、演算子の宣言が行われるクラスまたは構造体の型です。EitherS0
orT0
is the class or struct type in which the operator declaration takes place.S0
もT0
もinterface_typeではありません。NeitherS0
norT0
is an interface_type.- ユーザー定義の変換を除外すると、
S
からT
またはT
からS
への変換は存在しません。Excluding user-defined conversions, a conversion does not exist fromS
toT
or fromT
toS
.
ユーザー定義の変換に適用される制限については、「変換演算子」で詳しく説明します。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
型に存在する場合、A
もB
も*interface_type****に含ま***れていないと、A
がB
***を包含し***ていると言います。If a standard implicit conversion (Standard implicit conversions) exists from a typeA
to a typeB
, and if neitherA
norB
are interface_types, thenA
is said to be encompassed byB
, andB
is said to encompassA
. - 型のセットの中で最も外側にある型は、セット内の他のすべての型を含む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:
S0
とT0
の種類を決定します。Determine the typesS0
andT0
.S
またはT
が null 許容型である場合、S0
とT0
はその基になる型です。それ以外の場合は、S0
とT0
がそれぞれS
とT
になります。IfS
orT
are nullable types,S0
andT0
are their underlying types, otherwiseS0
andT0
are equal toS
andT
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 ofS0
(ifS0
is a class or struct), the base classes ofS0
(ifS0
is a class), andT0
(ifT0
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 inD
that convert from a type encompassingS
to a type encompassed byT
.U
が空の場合、変換は定義されていないため、コンパイル時エラーが発生します。IfU
is empty, the conversion is undefined and a compile-time error occurs. U
内の演算子の最も具体的なソースの種類であるSX
を検索します。Find the most specific source type,SX
, of the operators inU
:U
内のいずれかの演算子がS
から変換される場合、SX
はS
ます。If any of the operators inU
convert fromS
, thenSX
isS
.- それ以外の場合、
SX
はU
内の演算子のソースの種類の組み合わせにおいて最も包含されている型です。Otherwise,SX
is the most encompassed type in the combined set of source types of the operators inU
. 最も包含されている型が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 inU
:U
のいずれかの演算子がT
に変換される場合、TX
はT
ます。If any of the operators inU
convert toT
, thenTX
isT
.- それ以外の場合、
TX
は、U
内の演算子の対象の型を組み合わせたセット内で最も外側にある型になります。Otherwise,TX
is the most encompassing type in the combined set of target types of the operators inU
. 最も外側の型が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
場合は、これが最も具体的な変換演算子です。IfU
contains exactly one user-defined conversion operator that converts fromSX
toTX
, then this is the most specific conversion operator.- それ以外の
U
場合、SX
からTX
に変換するリフト変換演算子が1つだけ含まれている場合は、これが最も具体的な変換演算子になります。Otherwise, ifU
contains exactly one lifted conversion operator that converts fromSX
toTX
, then this is the most specific conversion operator. - それ以外の場合、変換はあいまいで、コンパイル時エラーが発生します。Otherwise, the conversion is ambiguous and a compile-time error occurs.
- 最後に、変換を適用します。Finally, apply the conversion:
S
がSX
ない場合は、S
からSX
への標準の暗黙的な変換が実行されます。IfS
is notSX
, then a standard implicit conversion fromS
toSX
is performed.SX
からTX
に変換するために、最も具体的な変換演算子が呼び出されます。The most specific conversion operator is invoked to convert fromSX
toTX
.TX
がT
ない場合は、TX
からT
への標準の暗黙的な変換が実行されます。IfTX
is notT
, then a standard implicit conversion fromTX
toT
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:
S0
とT0
の種類を決定します。Determine the typesS0
andT0
.S
またはT
が null 許容型である場合、S0
とT0
はその基になる型です。それ以外の場合は、S0
とT0
がそれぞれS
とT
になります。IfS
orT
are nullable types,S0
andT0
are their underlying types, otherwiseS0
andT0
are equal toS
andT
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 ofS0
(ifS0
is a class or struct), the base classes ofS0
(ifS0
is a class),T0
(ifT0
is a class or struct), and the base classes ofT0
(ifT0
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 inD
that convert from a type encompassing or encompassed byS
to a type encompassing or encompassed byT
.U
が空の場合、変換は定義されていないため、コンパイル時エラーが発生します。IfU
is empty, the conversion is undefined and a compile-time error occurs. U
内の演算子の最も具体的なソースの種類であるSX
を検索します。Find the most specific source type,SX
, of the operators inU
:U
内のいずれかの演算子がS
から変換される場合、SX
はS
ます。If any of the operators inU
convert fromS
, thenSX
isS
.- それ以外の場合、
U
内のいずれかの演算子がS
を含む型から変換される場合、SX
は、それらの演算子のソース型の組み合わせで最も包含されている型になります。Otherwise, if any of the operators inU
convert from types that encompassS
, thenSX
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. - それ以外の場合、
SX
はU
内の演算子のソースの種類の組み合わせにおいて最も外側の型になります。Otherwise,SX
is the most encompassing type in the combined set of source types of the operators inU
. 最も外側の型が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 inU
:U
のいずれかの演算子がT
に変換される場合、TX
はT
ます。If any of the operators inU
convert toT
, thenTX
isT
.- それ以外の場合、
U
内のいずれかの演算子がT
によって包含されている型に変換される場合、TX
は、それらの演算子の対象となる型の組み合わせのセット内で最も外側の型になります。Otherwise, if any of the operators inU
convert to types that are encompassed byT
, thenTX
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 inU
. 最も包含されていない型が見つからない場合は、変換があいまいになり、コンパイル時エラーが発生します。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
場合は、これが最も具体的な変換演算子です。IfU
contains exactly one user-defined conversion operator that converts fromSX
toTX
, then this is the most specific conversion operator.- それ以外の
U
場合、SX
からTX
に変換するリフト変換演算子が1つだけ含まれている場合は、これが最も具体的な変換演算子になります。Otherwise, ifU
contains exactly one lifted conversion operator that converts fromSX
toTX
, then this is the most specific conversion operator. - それ以外の場合、変換はあいまいで、コンパイル時エラーが発生します。Otherwise, the conversion is ambiguous and a compile-time error occurs.
- 最後に、変換を適用します。Finally, apply the conversion:
S
がSX
ない場合は、S
からSX
への標準の明示的な変換が実行されます。IfS
is notSX
, then a standard explicit conversion fromS
toSX
is performed.SX
からTX
に変換するために、ユーザー定義の最も限定的な変換演算子が呼び出されます。The most specific user-defined conversion operator is invoked to convert fromSX
toTX
.TX
がT
ない場合は、TX
からT
への標準の明示的な変換が実行されます。IfTX
is notT
, then a standard explicit conversion fromTX
toT
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:
F
にanonymous_function_signatureが含まれている場合は、D
とF
のパラメーターの数が同じになります。IfF
contains an anonymous_function_signature, thenD
andF
have the same number of parameters.F
にanonymous_function_signatureが含まれていない場合、D
のパラメーターにout
parameter 修飾子が指定されていない限り、D
には任意の型の0個以上のパラメーターを含めることができます。IfF
does not contain an anonymous_function_signature, thenD
may have zero or more parameters of any type, as long as no parameter ofD
has theout
parameter modifier.F
に明示的に型指定されたパラメーターリストがある場合、D
内の各パラメーターの型と修飾子はF
内の対応するパラメーターと同じになります。IfF
has an explicitly typed parameter list, each parameter inD
has the same type and modifiers as the corresponding parameter inF
.F
に暗黙的に型指定されたパラメーターリストがある場合、D
にはref
またはout
パラメーターがありません。IfF
has an implicitly typed parameter list,D
has noref
orout
parameters.F
の本体が式であり、D
がvoid
の戻り値の型であるか、またはF
が非同期であり、D
の戻り値の型がTask
である場合、F
の本体は、D
( 式ステートメント) として許可される有効な式 (wrt式) になります。If the body ofF
is an expression, and eitherD
has avoid
return type orF
is async andD
has the return typeTask
, then when each parameter ofF
is given the type of the corresponding parameter inD
, the body ofF
is a valid expression (wrt Expressions) that would be permitted as a statement_expression (Expression statements).F
の本体がステートメントブロックであり、D
がvoid
の戻り値の型を持っている場合、またはF
が非同期で、D
の戻り値の型がTask
の場合、F
の本体は有効なステートメントブロック (wrt block) で、D
ステートメントで式が指定されていません。If the body ofF
is a statement block, and eitherD
has avoid
return type orF
is async andD
has the return typeTask
, then when each parameter ofF
is given the type of the corresponding parameter inD
, the body ofF
is a valid statement block (wrt Blocks) in which noreturn
statement specifies an expression.F
の本体が式であり 、F
が非同期ではなく、D
の戻り値のT
型が void でない場合、またはF
が async で、D
が戻り値の型Task<T>
の場合、F
の本体は、暗黙的にD
に変換できる有効な式 (wrt式) になります。If the body ofF
is an expression, and eitherF
is non-async andD
has a non-void return typeT
, orF
is async andD
has a return typeTask<T>
, then when each parameter ofF
is given the type of the corresponding parameter inD
, the body ofF
is a valid expression (wrt Expressions) that is implicitly convertible toT
.F
の本体がステートメントブロックで、F
が非同期ではなく、D
が void 以外の戻り値の型T
の場合、またはF
が async でD
が戻り値の型Task<T>
である場合、F
の各パラメーターにD
の対応するパラメーターの型が指定されている場合、F
の本体は到達できないエンドポイントを持つ有効なステートメントブロック (wrt block) です。この場合、各return
ステートメントは、暗黙的に変換可能な式を指定します。If the body ofF
is a statement block, and eitherF
is non-async andD
has a non-void return typeT
, orF
is async andD
has a return typeTask<T>
, then when each parameter ofF
is given the type of the corresponding parameter inD
, the body ofF
is a valid statement block (wrt Blocks) with a non-reachable end point in which eachreturn
statement specifies an expression that is implicitly convertible toT
.
簡潔にするために、このセクションでは、タスクの種類 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 methodM
is selected corresponding to a method invocation (Method invocations) of the formE(A)
, with the following modifications:- 引数リスト
A
は式のリストであり、それぞれが変数として分類され、D
のformal_parameter_list内の対応するパラメーターの型と修飾子 (ref
またはout
) を使用します。The argument listA
is a list of expressions, each classified as a variable and with the type and modifier (ref
orout
) of the corresponding parameter in the formal_parameter_list ofD
. - 考慮される候補メソッドは、通常の形式 (適用可能な関数メンバー) で適用可能なメソッドのみであり、拡張フォームにのみ適用されるものではありません。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 methodM
having the same number of parameters asD
and the conversion is considered to exist. - 選択されたメソッド
M
は、デリゲート型D
と互換性がある (デリゲート互換性) 必要があります。そうでない場合は、コンパイル時エラーが発生します。The selected methodM
must be compatible (Delegate compatibility) with the delegate typeD
, or otherwise, a compile-time error occurs. - 選択したメソッド
M
がインスタンスメソッドの場合、E
に関連付けられたインスタンス式によって、デリゲートのターゲットオブジェクトが決定されます。If the selected methodM
is an instance method, the instance expression associated withE
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 typeD
, 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 ofE(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
への代入は、メソッドグループ F
を D1
型の値に暗黙的に変換します。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 withE
:- インスタンス式が評価されます。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 isnull
, aSystem.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 isnull
. D
デリゲート型の新しいインスタンスが割り当てられます。A new instance of the delegate typeD
is allocated. 新しいインスタンスの割り当てに使用できるメモリが不足している場合は、System.OutOfMemoryException
がスローされ、それ以上の手順は実行されません。If there is not enough memory available to allocate the new instance, aSystem.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.