Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Eine flexible Typanmerkung gibt an, dass ein Parameter, eine Variable oder ein Wert einen Typ aufweist, der mit einem angegebenen Typ kompatibel ist, wobei die Kompatibilität durch die Position in einer objektorientierten Hierarchie von Klassen oder Schnittstellen bestimmt wird. Flexible Typen sind besonders hilfreich, wenn die automatische Konvertierung in Typen, die höher in der Typhierarchie sind, nicht auftritt, aber Sie möchten ihre Funktionalität dennoch für die Arbeit mit jedem Typ in der Hierarchie oder einem beliebigen Typ aktivieren, der eine Schnittstelle implementiert.
Syntax
#type
Bemerkungen
In der vorherigen Syntax stellt der Typ einen Basistyp oder eine Schnittstelle dar.
Ein flexibler Typ entspricht einem generischen Typ, der eine Einschränkung aufweist, die die zulässigen Typen auf Typen beschränkt, die mit dem Basis- oder Schnittstellentyp kompatibel sind. Das heißt, die folgenden beiden Codezeilen sind gleichwertig.
#SomeType
'T when 'T :> SomeType
Flexible Typen sind in verschiedenen Situationen nützlich. Wenn Sie z. B. über eine Funktion mit höherer Reihenfolge verfügen (eine Funktion, die eine Funktion als Argument verwendet), ist es häufig nützlich, dass die Funktion einen flexiblen Typ zurückgibt. Im folgenden Beispiel ermöglicht die Verwendung eines flexiblen Typs mit einem Sequenzargument iterate2
in der höheren Reihenfolge funktionen das Arbeiten mit Funktionen, die Sequenzen, Arrays, Listen und alle anderen aufzählbaren Typen generieren.
Betrachten Sie die folgenden beiden Funktionen, von denen eine Sequenz zurückgegeben wird, die andere einen flexiblen Typ zurückgibt.
let iterate1 (f : unit -> seq<int>) =
for e in f() do printfn "%d" e
let iterate2 (f : unit -> #seq<int>) =
for e in f() do printfn "%d" e
// Passing a function that takes a list requires a cast.
iterate1 (fun () -> [1] :> seq<int>)
// Passing a function that takes a list to the version that specifies a
// flexible type as the return value is OK as is.
iterate2 (fun () -> [1])
Betrachten Sie als weiteres Beispiel die Seq.concat-Bibliotheksfunktion :
val concat: sequences:seq<#seq<'T>> -> seq<'T>
Sie können eine der folgenden aufzählbaren Sequenzen an diese Funktion übergeben:
- Eine Liste mit Listen
- Eine Liste von Arrays
- Ein Array von Listen
- Ein Array von Sequenzen
- Jede andere Kombination aus aufzählbaren Sequenzen
Der folgende Code verwendet Seq.concat
, um die Szenarien zu veranschaulichen, die Sie mithilfe flexibler Typen unterstützen können.
let list1 = [1;2;3]
let list2 = [4;5;6]
let list3 = [7;8;9]
let concat1 = Seq.concat [ list1; list2; list3]
printfn "%A" concat1
let array1 = [|1;2;3|]
let array2 = [|4;5;6|]
let array3 = [|7;8;9|]
let concat2 = Seq.concat [ array1; array2; array3 ]
printfn "%A" concat2
let concat3 = Seq.concat [| list1; list2; list3 |]
printfn "%A" concat3
let concat4 = Seq.concat [| array1; array2; array3 |]
printfn "%A" concat4
let seq1 = { 1 .. 3 }
let seq2 = { 4 .. 6 }
let seq3 = { 7 .. 9 }
let concat5 = Seq.concat [| seq1; seq2; seq3 |]
printfn "%A" concat5
Die Ausgabe lautet wie folgt.
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
seq [1; 2; 3; 4; ...]
In F# gibt es wie in anderen objektorientierten Sprachen Kontexte, in denen abgeleitete Typen oder Typen, die Schnittstellen implementieren, automatisch in einen Basistyp oder Schnittstellentyp konvertiert werden. Diese automatischen Konvertierungen treten in direkten Argumenten auf, aber nicht, wenn sich der Typ in einer untergeordneten Position befindet, als Teil eines komplexeren Typs, z. B. eines Rückgabetyps eines Funktionstyps oder als Typargument. Daher ist die flexible Schreibweise in erster Linie nützlich, wenn der Typ, auf den Sie sie anwenden, Teil eines komplexeren Typs ist.