共用方式為


轉型和轉換 (F#)

本主題描述 F# 對型別轉換的支援。

算術型別

F# 提供用於各種基本型別之間 (例如整數和浮點型別之間) 算術轉換的轉換運算子。 整數和字元轉換運算子都有已檢查和未檢查形式,而浮點運算子和 enum 轉換運算子則沒有。 未檢查形式是在 Microsoft.FSharp.Core.Operators 中定義,而已檢查形式則是在 Microsoft.FSharp.Core.Operators.Checked 中定義。 檢查形式會檢查溢位,如果結果值超出目標型別的限制,則會產生執行階段例外狀況。

上述每個運算子的名稱都與目的型別的名稱相同。 例如,在下列程式碼中,型別已明確標註,byte 會有兩個不同的意義。 第一次出現的 byte 為型別,第二次出現的 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 型別。 當它轉換為列舉型別時,型別推斷會嘗試判斷要轉換為 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"

您也可以明確指定目標的列舉別做為型別參數,下列程式碼所示:

let col3 = enum<Color> 3

請注意,列舉轉換工作,只有列舉的基礎型別是相容於所轉換的型別。 在下列程式碼中,轉換失敗進行編譯,因為不相配的int32和uint32。

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

如需詳細資訊,請參閱 列舉 (F#)

物件型別轉型

物件階層架構中的型別轉換是物件導向程式設計的基本。 有兩種基本轉換:向上轉型 (Upcasting) 和向下轉型 (Downcasting)。 在階層中向上轉型表示從衍生的物件參考轉型為基底物件參考。 只要基底類別是在衍生類別的繼承階層中,這類轉型保證會成功。 在階層中向下轉型表示從基底物件參考轉型為衍生的物件參考。只有在物件實際上是正確目的 (衍生) 型別的執行個體,或衍生自目的型別之型別的執行個體時,向下轉型才會成功。

F# 提供這些轉換類型的運算子。 :> 運算子會在階層中向上轉型,而 :?> 運算子則會在階層中向下轉型。

Dd233220.collapse_all(zh-tw,VS.110).gif向上轉型

在許多物件導向語言中,向上轉型為隱含,而在 F# 中,規則稍微不同。 當您將引數傳遞至物件型別上的方法時,會自動套用向上轉型。 不過,對於模組中使用 let 繫結的函式,除非參數型別宣告為彈性型別,否則不會自動套用向上轉型。 如需詳細資訊,請參閱彈性型別 (F#)

:> 運算子會執行靜態轉型,這表示是在編譯時期決定轉型是否成功。 如果使用 :> 的轉型成功編譯,它就是有效轉型,因此在執行階段不可能失敗。

您也可以使用 upcast 運算子來執行這類轉換。 下列運算式會指定在階層中向上轉換。

upcast expression

當您使用向上轉型運算子時,編譯器會嘗試從內容中推斷轉換的目標型別。 如果編譯器無法判斷目標型別,就會回報錯誤。

Dd233220.collapse_all(zh-tw,VS.110).gif向下轉型

:?> 運算子會執行動態轉型,這表示是在執行階段決定轉型是否成功。 在編譯時期不會檢查使用 :?> 運算子的轉型,但是在執行階段則會嘗試轉型為指定的型別。 如果物件與目標型別相容,轉型便會成功。 如果物件與目標型別不相容,執行階段會引發 InvalidCastException。

您也可以使用 downcast 運算子來執行動態型別轉換。 下列運算式會指定在階層中向下轉換為從程式內容推斷的型別。

downcast expression

如同向上轉型運算子,如果編譯器無法從內容推斷特定的目標型別,就會回報錯誤。

在下列程式碼中,會示範 :> 和 :?> 運算子的用法。 其中說明當您知道轉換會成功時最適合使用 :?> 運算子,因為它會在轉換失敗時擲回 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

with

base1 = upcast d1

在上述程式碼中,引數型別和傳回型別分別是 Derived1 和 Base1。

如需型別測試的詳細資訊,請參閱搜尋運算式 (F#)

請參閱

其他資源

F# 語言參考