キャストと変換 (F#)Casting and Conversions (F#)

このトピックでは、でF#の型変換のサポートについて説明します。This topic describes support for type conversions in F#.

算術型Arithmetic Types

F#整数型と浮動小数点型の間など、さまざまなプリミティブ型間の算術変換のための変換演算子を提供します。F# provides conversion operators for arithmetic conversions between various primitive types, such as between integer and floating point types. 整数および文字の変換演算子は、チェックされたフォームと unchecked 形式を持っています。浮動小数点演算子と enum 変換演算子にはありません。The integral and char conversion operators have checked and unchecked forms; the floating point operators and the enum conversion operator do not. オフになっているフォームは Microsoft.FSharp.Core.Operators で定義され、チェックされたフォームは Microsoft.FSharp.Core.Operators.Checkedで定義されます。The unchecked forms are defined in Microsoft.FSharp.Core.Operators and the checked forms are defined in Microsoft.FSharp.Core.Operators.Checked. 結果の値が対象の型の制限を超えた場合に、チェックされたフォームがオーバーフローをチェックし、ランタイム例外を生成します。The checked forms check for overflow and generate a runtime exception if the resulting value exceeds the limits of the target type.

これらの各演算子には、変換先の型の名前と同じ名前が付けられています。Each of these operators has the same name as the name of the destination type. たとえば、次のコードでは、型に明示的に注釈が付けられているため、byte は2つの異なる意味で表示されます。For example, in the following code, in which the types are explicitly annotated, byte appears with two different meanings. 最初の出現は型で、2番目は変換演算子です。The first occurrence is the type and the second is the conversion operator.

let x : int = 5

let b : byte = byte x

次の表に、でF#定義されている変換演算子を示します。The following table shows conversion operators defined in F#.

演算子Operator 説明Description
byte 8ビットの符号なしの型である byte に変換します。Convert to byte, an 8-bit unsigned type.
sbyte 符号付きバイトに変換します。Convert to signed byte.
int16 16ビット符号付き整数に変換します。Convert to a 16-bit signed integer.
uint16 16ビット符号なし整数に変換します。Convert to a 16-bit unsigned integer.
int32, int 32ビット符号付き整数に変換します。Convert to a 32-bit signed integer.
uint32 32ビット符号なし整数に変換します。Convert to a 32-bit unsigned integer.
int64 64ビット符号付き整数に変換します。Convert to a 64-bit signed integer.
uint64 64ビット符号なし整数に変換します。Convert to a 64-bit unsigned integer.
nativeint ネイティブの整数に変換します。Convert to a native integer.
unativeint 符号なしのネイティブ整数に変換します。Convert to an unsigned native integer.
float, double 64ビットの倍精度 IEEE 浮動小数点数に変換します。Convert to a 64-bit double-precision IEEE floating point number.
float32, single 32ビットの単精度 IEEE 浮動小数点数に変換します。Convert to a 32-bit single-precision IEEE floating point number.
decimal System.Decimalに変換します。Convert to System.Decimal.
char Unicode 文字 System.Charに変換します。Convert to System.Char, a Unicode character.
enum 列挙型に変換します。Convert to an enumerated type.

これらの演算子は、組み込みのプリミティブ型に加えて、適切なシグネチャを持つ op_Explicit または op_Implicit メソッドを実装する型で使用できます。In addition to built-in primitive types, you can use these operators with types that implement op_Explicit or op_Implicit methods with appropriate signatures. たとえば、int 変換演算子は、型をパラメーターとして受け取り、intを返す静的メソッド op_Explicit を提供する任意の型で動作します。For example, the int conversion operator works with any type that provides a static method op_Explicit that takes the type as a parameter and returns int. メソッドが戻り値の型によってオーバーロードできないという一般的な規則に対する特別な例外として、op_Explicitop_Implicitに対してこれを行うことができます。As a special exception to the general rule that methods cannot be overloaded by return type, you can do this for op_Explicit and op_Implicit.

列挙型Enumerated Types

enum 演算子は、変換先の enum の型を表す1つの型パラメーターを受け取る汎用演算子です。The enum operator is a generic operator that takes one type parameter that represents the type of the enum to convert to. 列挙型に変換すると、型推論は、変換先の enum の型を決定しようとします。When it converts to an enumerated type, type inference attempts to determine the type of the enum that you want to convert to. 次の例では、変数 col1 に明示的に注釈が付けられていませんが、その型は後の等値テストから推論されます。In the following example, the variable col1 is not explicitly annotated, but its type is inferred from the later equality test. したがって、コンパイラは、Color 列挙型に変換していることを推測できます。Therefore, the compiler can deduce that you are converting to a Color enumeration. または、次の例の col2 のように、型の注釈を指定することもできます。Alternatively, you can supply a type annotation, as with col2 in the following example.

type Color =
    | Red = 1
    | Green = 2
    | Blue = 3

// The target type of the conversion cannot be determined by type inference, so the type parameter must be explicit.
let col1 = enum<Color> 1

// The target type is supplied by a type annotation.
let col2 : Color = enum 2

次のコードのように、ターゲットの列挙型を明示的に型パラメーターとして指定することもできます。You can also specify the target enumeration type explicitly as a type parameter, as in the following code:

let col3 = enum<Color> 3

列挙キャストは、列挙型の基になる型が変換される型と互換性がある場合にのみ機能します。Note that the enumeration casts work only if the underlying type of the enumeration is compatible with the type being converted. 次のコードでは、int32uint32が一致しないため、変換に失敗します。In the following code, the conversion fails to compile because of the mismatch between int32 and uint32.

// Error: types are incompatible
let col4 : Color = enum 2u

詳細については、「列挙型」を参照してください。For more information, see Enumerations.

キャスト (オブジェクト型を)Casting Object Types

オブジェクト階層内の型間の変換は、オブジェクト指向プログラミングの基本となります。Conversion between types in an object hierarchy is fundamental to object-oriented programming. 変換には、キャスト (キャスト) とキャストダウン (ダウンキャスト) の2つの基本的な種類があります。There are two basic types of conversions: casting up (upcasting) and casting down (downcasting). 階層をキャストすることは、派生オブジェクト参照からベースオブジェクト参照へのキャストを意味します。Casting up a hierarchy means casting from a derived object reference to a base object reference. このようなキャストは、基底クラスが派生クラスの継承階層内にある限り、確実に動作します。Such a cast is guaranteed to work as long as the base class is in the inheritance hierarchy of the derived class. 基底オブジェクト参照から派生オブジェクト参照への階層のキャストは、オブジェクトが実際には正しい宛先 (派生) 型のインスタンスであるか、または変換先の型から派生した型である場合にのみ成功します。Casting down a hierarchy, from a base object reference to a derived object reference, succeeds only if the object actually is an instance of the correct destination (derived) type or a type derived from the destination type.

F#は、これらの種類の変換のための演算子を提供します。F# provides operators for these types of conversions. :> 演算子は階層をキャストし、:?> 演算子は階層を下位にキャストします。The :> operator casts up the hierarchy, and the :?> operator casts down the hierarchy.

キャストUpcasting

多くのオブジェクト指向言語では、キャストは暗黙的です。でF#は、ルールが若干異なります。In many object-oriented languages, upcasting is implicit; in F#, the rules are slightly different. キャストは、オブジェクト型のメソッドに引数を渡すときに自動的に適用されます。Upcasting is applied automatically when you pass arguments to methods on an object type. ただし、モジュール内の let バインド関数の場合、パラメーターの型が柔軟な型として宣言されていない限り、キャストは自動ではありません。However, for let-bound functions in a module, upcasting is not automatic, unless the parameter type is declared as a flexible type. 詳細については、「柔軟な型」を参照してください。For more information, see Flexible Types.

:> 演算子は静的なキャストを実行します。これは、キャストの成功がコンパイル時に決定されることを意味します。The :> operator performs a static cast, which means that the success of the cast is determined at compile time. :> を使用するキャストが正常にコンパイルされた場合、それは有効なキャストであり、実行時に失敗する可能性はありません。If a cast that uses :> compiles successfully, it is a valid cast and has no chance of failure at run time.

また、upcast 演算子を使用して、このような変換を実行することもできます。You can also use the upcast operator to perform such a conversion. 次の式では、階層の上位変換が指定されています。The following expression specifies a conversion up the hierarchy:

upcast expression

アップキャスト演算子を使用すると、コンパイラはコンテキストから変換先の型を推論しようとします。When you use the upcast operator, the compiler attempts to infer the type you are converting to from the context. コンパイラがターゲットの型を判断できない場合、コンパイラはエラーを報告します。If the compiler is unable to determine the target type, the compiler reports an error. 型の注釈が必要な可能性があります。A type annotation may be required.

ダウンキャストDowncasting

:?> 演算子は動的キャストを実行します。これは、キャストの成功が実行時に決定されることを意味します。The :?> operator performs a dynamic cast, which means that the success of the cast is determined at run time. :?> 演算子を使用するキャストは、コンパイル時にはチェックされません。ただし、実行時には、指定された型にキャストしようとしました。A cast that uses the :?> operator is not checked at compile time; but at run time, an attempt is made to cast to the specified type. オブジェクトがターゲット型と互換性がある場合、キャストは成功します。If the object is compatible with the target type, the cast succeeds. オブジェクトがターゲット型と互換性がない場合、ランタイムは InvalidCastExceptionを発生させます。If the object is not compatible with the target type, the runtime raises an InvalidCastException.

downcast 演算子を使用して、動的な型変換を実行することもできます。You can also use the downcast operator to perform a dynamic type conversion. 次の式は、階層の下位への変換を、プログラムコンテキストから推論される型に指定します。The following expression specifies a conversion down the hierarchy to a type that is inferred from program context:

downcast expression

upcast 演算子と同様に、コンパイラがコンテキストから特定のターゲット型を推論できない場合は、エラーが報告されます。As for the upcast operator, if the compiler cannot infer a specific target type from the context, it reports an error. 型の注釈が必要な可能性があります。A type annotation may be required.

次のコードは、:> 演算子と :?> 演算子の使用方法を示しています。The following code illustrates the use of the :> and :?> operators. このコードは、変換が成功することがわかっている場合に :?> 演算子が最適に使用されることを示しています。変換に失敗した場合は InvalidCastException がスローされるためです。The code illustrates that the :?> operator is best used when you know that conversion will succeed, because it throws InvalidCastException if the conversion fails. 変換が成功したことがわからない場合は、例外を生成するオーバーヘッドを回避するため、match 式を使用する型テストの方が適しています。If you do not know that a conversion will succeed, a type test that uses a match expression is better because it avoids the overhead of generating an exception.

type Base1() =
    abstract member F : unit -> unit
    default u.F() =
     printfn "F Base1"

type Derived1() =
    inherit Base1()
    override u.F() =
      printfn "F Derived1"


let d1 : Derived1 = Derived1()

// Upcast to Base1.
let base1 = d1 :> Base1

// This might throw an exception, unless
// you are sure that base1 is really a Derived1 object, as
// is the case here.
let derived1 = base1 :?> Derived1

// If you cannot be sure that b1 is a Derived1 object,
// use a type test, as follows:
let downcastBase1 (b1 : Base1) =
   match b1 with
   | :? Derived1 as derived1 -> derived1.F()
   | _ -> ()

downcastBase1 base1

ジェネリック演算子 downcastupcast は型の推定に依存して引数と戻り値の型を決定するため、上記のコードでは、Because generic operators downcast and upcast rely on type inference to determine the argument and return type, in the above code, you can replace

let base1 = d1 :> Base1

withwith

let base1: Base1 = upcast d1

型の注釈が必要であることに注意してください。これは upcast 自体が基底クラスを特定できなかったためです。Note that a type annotation is required, since upcast by itself could not determine the base class.

参照See also