Umwandlung und Konvertierungen (F#)
In diesem Thema wird die Unterstützung für Typkonvertierungen in F# beschrieben.
Arithmetische Typen
F# stellt Konvertierungsoperatoren für arithmetische Konvertierungen zwischen verschiedenen primitiven Typen bereit, z. B. zwischen ganzzahligen Typen und Gleitkommatypen.Die Operatoren für die Konvertierung von ganzzahligen Typen und der char-Konvertierungsoperator sind in checked- und unchecked-Formen verfügbar, nicht jedoch Gleitkommaoperatoren und der enum-Konvertierungsoperator.Die unchecked-Formen werden in Microsoft.FSharp.Core.Operators und die checked-Formen in Microsoft.FSharp.Core.Operators.Checked definiert.Die checked-Formen überprüfen auf Überlauf und generieren eine Laufzeitausnahme, wenn der resultierende Wert den Grenzwert des Zieltyps überschreitet.
Jeder dieser Operatoren verfügt über den gleichen Namen wie der Name des Zieltyps.Beispielsweise ist im folgenden Code, in dem die Typen explizit gekennzeichnet sind, byte mit zwei verschiedenen Bedeutungen enthalten.Das erste Vorkommen ist der Typ, und das zweite Vorkommen ist der Konvertierungsoperator.
let x : int = 5
let b : byte = byte x
In der folgenden Tabelle werden in F# definierte Konvertierungsoperatoren angezeigt.
Operator |
Beschreibung |
---|---|
byte |
Konvertiert in Byte, ein 8-Bit-Typ ohne Vorzeichen. |
sbyte |
Konvertiert in Byte mit Vorzeichen. |
int16 |
Konvertiert in eine 16-Bit-Ganzzahl mit Vorzeichen. |
uint16 |
Konvertiert in eine 16-Bit-Ganzzahl ohne Vorzeichen. |
int32, int |
Konvertiert in eine 32-Bit-Ganzzahl mit Vorzeichen. |
uint32 |
Konvertiert in eine 32-Bit-Ganzzahl ohne Vorzeichen. |
int64 |
Konvertiert in eine 64-Bit-Ganzzahl mit Vorzeichen. |
uint64 |
Konvertiert in eine 64-Bit-Ganzzahl ohne Vorzeichen. |
nativeint |
Konvertieren Sie in eine systemeigene ganze Zahl. |
unativeint |
Konvertiert in eine systemeigene ganze Zahl ohne Vorzeichen. |
float, double |
Konvertiert in eine 64-Bit-IEEE-Gleitkommazahl mit doppelter Genauigkeit. |
float32, single |
Konvertiert in eine 32-Bit-IEEE-Gleitkommazahl mit einfacher Genauigkeit. |
decimal |
Konvertiert in System.Decimal. |
char |
Konvertiert in System.Char, ein Unicode-Zeichen. |
enum |
Konvertiert in einen Aufzählungstyp. |
Zusätzlich zu integrierten primitiven Typen können Sie diese Operatoren mit Typen verwenden, die die op_Explicit- oder op_Implicit-Methode mit entsprechenden Signaturen implementieren.Der int-Konvertierungsoperator funktioniert z. B. mit jedem Typ, der eine statische op_Explicit-Methode bereitstellt, die den Typ als Parameter akzeptiert und int zurückgibt.Als besondere Ausnahme von der allgemeinen Regel, dass Methoden nicht pro Rückgabetyp überladen werden können, ist dies bei op_Explicit und op_Implicit möglich.
Enumerationstypen
Der Operator enum ist ein generischer Operator. Dieser akzeptiert einen Typparameter, der den Typ der enum darstellt, in den konvertiert werden soll.Bei der Konvertierung in einen Aufzählungstyp wird mithilfe von Typrückschluss versucht, den Typ der enum zu bestimmen, in den konvertiert werden soll.Im folgenden Beispiel wird die Variable col1 nicht explizit gekennzeichnet, jedoch wird ihr Typ aus dem später erfolgenden Gleichheitstest abgeleitet.Daher kann der Compiler folgern, dass in eine Color-Enumeration konvertiert wird.Alternativ können Sie eine Typanmerkung angeben, wie für col2 im folgenden Beispiel:
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"
Mit dem Ziel enumerationstyp als Typparameter, wie im folgenden Code auch explizit angeben:
let col3 = enum<Color> 3
Beachten Sie, dass die Enumeration umwandlungen funktionieren nur, wenn der zugrunde liegende Typ der Enumeration mit dem Typ kompatibel ist, die konvertiert wird.Im folgenden Code wird die Konvertierung aufgrund eines Konflikts zwischen int32 und uint32nicht kompiliert.
// Error: types are incompatible
let col4 : Color = enum 2u
Weitere Informationen finden Sie unter Enumerationen (F#).
Umwandeln von Objekttypen
Die Konvertierung in Typen in einer Objekthierarchie ist bei der objektorientierten Programmierung von grundlegender Bedeutung.Es gibt zwei grundlegende Typen von Konvertierungen: Aufwärtsumwandlung (Upcasting) und Abwärtswandlung (Downcasting).Bei der Aufwärtsumwandlung in einer Hierarchie wird ein abgeleiteter Objektverweis in einen Basisobjektverweis umgewandelt.Die Ausführung einer solchen Umwandlung ist sichergestellt, solange sich die Basisklasse in der Vererbungshierarchie der abgeleiteten Klasse befindet.Die Abwärtsumwandlung in einer Hierarchie, d. h. die Umwandlung eines Basisobjektverweises in einen abgeleiteten Objektverweis, ist nur möglich, wenn das Objekt tatsächlich eine Instanz des ordnungsgemäßen Zieltyps (abgeleiteten Typs) oder eines vom Zieltyp abgeleiteten Typs ist.
In F# werden Operatoren für diese Typen von Konvertierung bereitgestellt.Der Operator :> führt die Aufwärtsumwandlung in der Hierarchie und der Operator :?> die Abwärtsumwandlung in der Hierarchie aus.
Upcasting
In vielen objektorientierten Sprachen erfolgt Upcasting implizit. In F# gelten geringfügig andere Regeln.Upcasting wird automatisch angewendet, wenn Sie Argumente an Methoden für einen Objekttyp übergeben.Für Funktionen mit let-Bindung in einem Modul erfolgt Upcasting jedoch nicht automatisch, es sei denn, der Parametertyp ist als flexibler Typ deklariert.Weitere Informationen finden Sie unter Flexible Typen (F#).
Der Operator :> führt eine statische Umwandlung aus. Dies bedeutet, dass der Erfolg der Umwandlung zur Kompilierzeit bestimmt wird.Wenn eine Umwandlung mit :> erfolgreich kompiliert wird, ist die Umwandlung gültig, und zur Laufzeit kann kein Fehler auftreten.
Sie können eine solche Konvertierung auch mithilfe des Operators upcast ausführen.Der folgende Ausdruck gibt eine Aufwärtskonvertierung in der Hierarchie an.
upcast expression
Wenn Sie den Operator upcast verwenden, versucht der Compiler, den zu konvertierenden Typ aus dem Kontext abzuleiten.Wenn der Compiler den Zieltyp nicht bestimmen kann, gibt der Compiler einen Fehler aus.
Downcasting
Der Operator :?> führt eine dynamische Umwandlung aus. Dies bedeutet, dass der Erfolg der Umwandlung zur Laufzeit bestimmt wird.Eine Umwandlung mit dem Operator :?> wird nicht zur Kompilierzeit überprüft. Jedoch wird zur Laufzeit versucht, die Umwandlung in den angegebenen Typ auszuführen.Wenn das Objekt mit dem Zieltyp kompatibel ist, wird die Umwandlung erfolgreich ausgeführt.Wenn das Objekt nicht mit dem Zieltyp kompatibel ist, löst die Laufzeit eine InvalidCastException aus.
Sie können auch mithilfe des Operators downcast eine dynamische Typkonvertierung ausführen.Der folgende Ausdruck gibt eine Abwärtskonvertierung in der Hierarchie in einen Typ an, der aus dem Programmkontext abgeleitet wird.
downcast expression
Wie beim Operator upcast gibt der Compiler einen Fehler aus, wenn er keinen bestimmten Zieltyp aus dem Kontext ableiten kann.
Im folgenden Code wird die Verwendung des Operators :> und des Operators :?> veranschaulicht.Im Code wird veranschaulicht, dass sich die Verwendung des Operators :?> empfiehlt, wenn Sie wissen, dass die Konvertierung erfolgreich ausgeführt wird, da eine InvalidCastException ausgelöst wird, wenn die Konvertierung fehlschlägt.Wenn Sie nicht wissen, ob eine Konvertierung erfolgreich ausgeführt wird, empfiehlt sich ein Typtest, der einen match-Ausdruck verwendet, da auf diese Weise der Mehraufwand vermieden wird, eine Ausnahme zu generieren.
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
Da die generischen Operatoren downcast und upcast mithilfe von Typrückschluss den Argument- und Rückgabetyp bestimmen, können Sie im obigen Code
let base1 = d1 :> Base1
ersetzen durch
base1 = upcast d1
Im vorherigen Code lauten der Argumenttyp und der Rückgabetyp Derived1 bzw. Base1.
Weitere Informationen zu Typtests finden Sie unter Vergleichsausdrücke (F#).