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.
F#-Funktionswerte, Methoden, Eigenschaften und Aggregattypen wie Klassen, Datensätze und diskriminierte Vereinigungen können generisch sein. Generische Konstrukte enthalten mindestens einen Typparameter, der normalerweise vom Benutzer des generischen Konstrukts bereitgestellt wird. Mit generischen Funktionen und Typen können Sie Code schreiben, der mit einer Vielzahl von Typen funktioniert, ohne den Code für jeden Typ zu wiederholen. Das Erstellen eines generischen Codes kann in F# einfach sein, da Ihr Code häufig implizit von der Typableitung des Compilers und automatischen Generalisierungsmechanismen abgeleitet wird.
Syntax
// Explicitly generic function.
let function-name<type-parameters> parameter-list =
function-body
// Explicitly generic method.
[ static ] member object-identifier.method-name<type-parameters> parameter-list [ return-type ] =
method-body
// Explicitly generic class, record, interface, structure,
// or discriminated union.
type type-name<type-parameters> type-definition
Bemerkungen
Die Deklaration einer explizit generischen Funktion oder eines Typs ähnelt der einer nicht generischen Funktion oder eines Typs, mit Ausnahme der Spezifikation (und Verwendung) der Typparameter in winkeln Klammern nach der Funktion oder dem Typnamen.
Deklarationen sind häufig implizit generisch. Wenn Sie nicht vollständig den Typ jedes Parameters angeben, der zum Verfassen einer Funktion oder eines Typs verwendet wird, versucht der Compiler, den Typ der einzelnen Parameter, Werte und Variablen vom von Ihnen geschriebenen Code abzuleiten. Weitere Informationen finden Sie unter "Typinference". Wenn der Code für Den Typ oder die Funktion die Parametertypen andernfalls nicht einschränkt, ist die Funktion oder der Typ implizit generisch. Dieser Prozess wird als automatische Generalisierung bezeichnet. Es gibt einige Grenzwerte für die automatische Generalisierung. Wenn der F#-Compiler beispielsweise die Typen für ein generisches Konstrukt nicht ableiten kann, meldet der Compiler einen Fehler, der auf eine Einschränkung namens "Werteinschränkung" verweist. In diesem Fall müssen Sie möglicherweise einige Typanmerkungen hinzufügen. Weitere Informationen zur automatischen Generalisierung und der Werteinschränkung sowie zum Ändern des Codes zur Behebung des Problems finden Sie unter "Automatische Generalisierung".
In der vorherigen Syntax ist typparameter eine durch Trennzeichen getrennte Liste von Parametern, die unbekannte Typen darstellen, von denen jede mit einem einzelnen Anführungszeichen beginnt, optional mit einer Einschränkungsklausel, die weiter beschränkt, welche Typen für diesen Typparameter verwendet werden können. Informationen zur Syntax für Einschränkungsklauseln verschiedener Arten und andere Informationen zu Einschränkungen finden Sie unter "Constraints".
Die Typdefinition in der Syntax entspricht der Typdefinition für einen nicht generischen Typ. Sie enthält die Konstruktorparameter für einen Klassentyp, eine optionale as Klausel, das Gleichheitssymbol, die Datensatzfelder, die inherit Klausel, die Auswahlmöglichkeiten für eine diskriminierte Vereinigung let sowie do Bindungen, Memberdefinitionen und alles andere, was in einer nicht generischen Typdefinition zulässig ist.
Die anderen Syntaxelemente sind identisch mit denen für nicht generische Funktionen und Typen. Der Objektbezeichner ist z. B. ein Bezeichner, der das enthaltende Objekt selbst darstellt.
Eigenschaften, Felder und Konstruktoren dürfen nicht allgemeiner sein als der eingeschlossene Typ. Außerdem können Werte in einem Modul nicht generisch sein.
Implizit generische Konstrukte
Wenn der F#-Compiler die Typen in Ihrem Code ableitet, behandelt er automatisch jede Funktion, die generisch als generisch sein kann. Wenn Sie einen Typ explizit angeben, z. B. einen Parametertyp, verhindern Sie die automatische Generalisierung.
Im folgenden Codebeispiel makeList ist generisch, obwohl weder sie noch ihre Parameter explizit als generisch deklariert werden.
let makeList a b = [ a; b ]
Die Signatur der Funktion wird abgeleitet.'a -> 'a -> 'a list Beachten Sie, dass a und b in diesem Beispiel abgeleitet wird, dass sie denselben Typ aufweisen. Dies liegt daran, dass sie in einer Liste zusammen enthalten sind und alle Elemente einer Liste denselben Typ aufweisen müssen.
Sie können eine Funktion auch generisch machen, indem Sie die Syntax für einfache Anführungszeichen in einer Typanmerkung verwenden, um anzugeben, dass ein Parametertyp ein generischer Typparameter ist. Im folgenden Code ist generisch, function1 da seine Parameter auf diese Weise als Typparameter deklariert werden.
let function1 (x: 'a) (y: 'a) = printfn "%A %A" x y
Explizit generische Konstrukte
Sie können eine Funktion auch generisch machen, indem Sie die Typparameter explizit in winkeln Klammern (<type-parameter>) deklarieren. Der folgende Code veranschaulicht dies.
let function2<'T> (x: 'T) (y: 'T) = printfn "%A, %A" x y
Verwenden von generischen Konstrukten
Wenn Sie generische Funktionen oder Methoden verwenden, müssen Sie möglicherweise nicht die Typargumente angeben. Der Compiler verwendet typinferenz, um die entsprechenden Typargumente zu ableiten. Wenn es noch eine Mehrdeutigkeit gibt, können Sie Typargumente in winkeln Klammern angeben und mehrere Typargumente durch Kommas trennen.
Der folgende Code zeigt die Verwendung der Funktionen, die in den vorherigen Abschnitten definiert sind.
// In this case, the type argument is inferred to be int.
function1 10 20
// In this case, the type argument is float.
function1 10.0 20.0
// Type arguments can be specified, but should only be specified
// if the type parameters are declared explicitly. If specified,
// they have an effect on type inference, so in this example,
// a and b are inferred to have type int.
let function3 a b =
// The compiler reports a warning:
function1<int> a b
// No warning.
function2<int> a b
Hinweis
Es gibt zwei Möglichkeiten, auf einen generischen Typ nach Namen zu verweisen. Es gibt beispielsweise zwei Möglichkeiten, auf einen generischen Typ list zu verweisen, list<int>int list der über ein argument mit einem einzelnen Typ intverfügt. Letztere Form wird konventionell nur mit integrierten F#-Typen wie list z. B. und option. Wenn mehrere Typargumente vorhanden sind, verwenden Sie normalerweise die Syntax Dictionary<int, string> , aber Sie können auch die Syntax (int, string) Dictionaryverwenden.
Wildcards als Typargumente
Um anzugeben, dass ein Typargument vom Compiler abgeleitet werden soll, können Sie anstelle eines benannten Typarguments den Unterstrich oder das Wildcardsymbol (_) verwenden. Dies wird im folgenden Code gezeigt.
let printSequence (sequence1: Collections.seq<_>) =
Seq.iter (fun elem -> printf "%s " (elem.ToString())) sequence1
Einschränkungen in generischen Typen und Funktionen
In einer generischen Typ- oder Funktionsdefinition können Sie nur die Konstrukte verwenden, die für den generischen Typparameter verfügbar sind. Dies ist erforderlich, um die Überprüfung von Funktions- und Methodenaufrufen zur Kompilierungszeit zu aktivieren. Wenn Sie Die Typparameter explizit deklarieren, können Sie eine explizite Einschränkung auf einen generischen Typparameter anwenden, um den Compiler darüber zu informieren, dass bestimmte Methoden und Funktionen verfügbar sind. Wenn Sie jedoch zulassen, dass der F#-Compiler die generischen Parametertypen ableiten kann, bestimmt er die entsprechenden Einschränkungen für Sie. Weitere Informationen finden Sie unter Einschränkungen.
Parameter für statisch aufgelöste Typen
Es gibt zwei Arten von Typparametern, die in F#-Programmen verwendet werden können. Die erste sind generische Typparameter der Art, die in den vorherigen Abschnitten beschrieben werden. Diese erste Art von Typparameter entspricht den generischen Typparametern, die in Sprachen wie Visual Basic und C# verwendet werden. Eine andere Art von Typparameter ist spezifisch für F# und wird als statisch aufgelöster Typparameter bezeichnet. Weitere Informationen zu diesen Konstrukten finden Sie unter "Statisch aufgelöste Typparameter".
Beispiele
// A generic function.
// In this example, the generic type parameter 'a makes function3 generic.
let function3 (x: 'a) (y: 'a) = printf "%A %A" x y
// A generic record, with the type parameter in angle brackets.
type GR<'a> = { Field1: 'a; Field2: 'a }
// A generic class.
type C<'a>(a: 'a, b: 'a) =
let z = a
let y = b
member this.GenericMethod(x: 'a) = printfn "%A %A %A" x y z
// A generic discriminated union.
type U<'a> =
| Choice1 of 'a
| Choice2 of 'a * 'a
type Test() =
// A generic member
member this.Function1<'a>(x, y) = printfn "%A, %A" x y
// A generic abstract method.
abstract abstractMethod<'a, 'b> : 'a * 'b -> unit
override this.abstractMethod<'a, 'b>(x: 'a, y: 'b) = printfn "%A, %A" x y