キャストと変換 (F#)

更新 : 2010 年 9 月

このトピックでは、F# での型変換のサポートについて説明します。

数値型

F# には、整数型と浮動小数点型の間など、各種のプリミティブ型の間で算術変換を行うための変換演算子が用意されています。 整数変換演算子と char 変換演算子にはチェック形式と非チェック形式がありますが、浮動小数点変換演算子と enum 変換演算子にはありません。 非チェック形式は Microsoft.FSharp.Core.Operators で定義されており、チェック形式は Microsoft.FSharp.Core.Operators.Checked で定義されています。 チェック形式ではオーバーフローがチェックされ、結果値が対象の型の範囲を超えた場合にランタイム例外が生成されます。

これらの各演算子には、変換先の型の名前と同じ名前が付けられています。 たとえば、次のコードでは型が明示的に指定されていますが、byte は 2 つの異なる意味で使用されています。 1 つ目の byte は型を表し、2 つ目の byte は変換演算子を表しています。

let x : int = 5

let b : byte = byte x

次の表に、F# で定義されている変換演算子を示します。

演算子

説明

byte

バイト (8 ビットの符号なしの型) に変換します。

sbyte

符号付きバイトに変換します。

int16

16 ビット符号付き整数に変換します。

uint16

16 ビット符号なし整数に変換します。

int32, int

32 ビット符号付き整数に変換します。

uint32

32 ビット符号なし整数に変換します。

int64

64 ビット符号付き整数に変換します。

uint64

64 ビット符号なし整数に変換します。

nativeint

ネイティブ整数に変換します。

unativeint

符号なしネイティブ整数に変換します。

float, double

64 ビット IEEE 倍精度浮動小数点数に変換します。

float32, single

32 ビット IEEE 単精度浮動小数点数に変換します。

decimal

System.Decimal に変換します。

char

System.Char (Unicode 文字) に変換します。

enum

列挙型に変換します。

組み込みのプリミティブ型に加えて、適切なシグネチャを持つ op_Explicit メソッドまたは op_Implicit メソッドを実装する型でも、これらの演算子を使用できます。 たとえば、int 変換演算子は、パラメーターとして型を受け取って int を返す静的メソッド op_Explicit を備える任意の型で使用できます。 戻り値の型によってメソッドをオーバーロードすることはできないというのが一般的な規則ですが、特別な例外として、 op_Explicit および op_Implicit ではこれを実行できます。

列挙型

enum 演算子は変換先の enum の型を表す型パラメーターを 1 つ受け取るジェネリック演算子です。 この演算子を使用して列挙型への変換を行うと、型の推論によって変換先の enum の型が決定されます。 次の例の col1 変数は明示的には指定されていませんが、その型は、後半に記述されている等値テストから推論されます。 これにより、Color 列挙型に変換しようとしていることをコンパイラが推論できます。 また、次の例の col2 のように、型の注釈を指定することもできます。

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

// The target type of the conversion is determined by type inference.
let col1 = enum 1
// The target type is supplied by a type annotation.
let col2 : Color = enum 2 
do
    if (col1 = Color.Red) then
       printfn "Red"

オブジェクト型のキャスト

オブジェクト階層内の型の間での変換は、オブジェクト指向プログラミングでは必要不可欠です。 変換の基本的な種類には、上位へのキャスト (アップキャスト) と下位へのキャスト (ダウンキャスト) の 2 つがあります。 上位階層へのキャストとは、派生オブジェクト参照からベース オブジェクト参照にキャストすることです。 このキャストは、基本クラスが派生クラスの継承階層内にある限り、実行できることが保証されています。 下位階層へのキャストとは、ベース オブジェクト参照から派生オブジェクト参照にキャストすることであり、オブジェクトが実際には目的の変換先の型 (派生型) のインスタンスであるか、変換先の型から派生した型である場合にのみ成功します。

F# には、これらの種類の変換用に演算子が用意されています。 :> 演算子は上位階層へのキャストを行い、:?> 演算子は下位階層へのキャストを行います。

アップキャスト

多くのオブジェクト指向言語では、アップキャストが暗黙で行われますが、F# では若干規則が異なります。 アップキャストは、引数をオブジェクト型でメソッドに渡すときに自動的に適用されます。 ただし、モジュール内で let バインドされた関数の場合は、パラメーターの型が柔軟な型として宣言されていない限り、アップキャストは自動的には行われません。 詳細については、「柔軟な型 (F#)」を参照してください。

:> 演算子は静的なキャストを実行します。これは、キャストが成功するかどうかがコンパイル時に決まることを意味しています。 :> を使用したキャストのコンパイルが成功した場合、そのキャストは有効であり、実行時に失敗することはありません。

upcast 演算子を使用して、このような変換を実行することもできます。 次の式では、上位階層への変換を指定しています。

upcast expression

upcast 演算子を使用する場合は、コンパイラがコンテキストから変換先の型を推論しようとします。 コンパイラは、変換先の型を決定できない場合はエラーを報告します。

ダウンキャスト

:?> 演算子は動的なキャストを実行します。これは、キャストが成功するかどうかが実行時に決まることを意味しています。 :?> 演算子を使用したキャストはコンパイル時にはチェックされません。指定した型へのキャストは実行時に試行されます。 オブジェクトが変換先の型と互換性がある場合、キャストは成功します。 オブジェクトが変換先の型と互換性がない場合は、ランタイムにより InvalidCastException が発生します。

downcast 演算子を使用して、動的な型変換を実行することもできます。 次の式では、下位階層への変換を指定しています。変換先の型は、プログラム コンテキストから推論された型になります。

downcast expression

upcast 演算子を使用すると、コンパイラが特定の変換先の型をコンテキストから推論できない場合に、エラーが報告されます。

次のコードは、:> 演算子と :?> 演算子の使用例を示しています。 このコードは、変換が成功することが明らかな場合は、:?> 演算子を使用する方法が最適であることを示しています。これは、変換が失敗すると InvalidCastException がスローされるためです。 変換が成功するかどうかが不明な場合には、match 式を使用して型テストを行うことをお勧めします。型テストを行うと、例外の生成によるオーバーヘッドを回避できるためです。

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

ジェネリック演算子である downcast と upcast は、引数と戻り値の型を決定する際に型の推論を使用するため、上記のコードで次のように置き換えることができます。

let base1 = d1 :> Base1

これを次のように置き換えることができます。

base1 = upcast d1

前のコードの引数の型と戻り値の型は、それぞれ Derived1 と Base1 になります。

型テストの詳細については、「match 式 (F#)」を参照してください。

参照

その他の技術情報

F# 言語リファレンス

履歴の変更

日付

履歴

理由

2010 年 9 月

戻り値の型による op_Explicit および op_Implicit のオーバーロードに関する情報を追加しました。

情報の拡充