Typerweiterungen (F#)

Mithilfe von Typerweiterungen können Sie einem zuvor definierten Objekttyp neue Member hinzufügen.

// Intrinsic extension.
type typename with
   member self-identifier.member-name =
      body
   ...
   [ end ]

// Optional extension.
type typename with
   member self-identifier.member-name =
      body
   ...
   [ end ]

Hinweise

Es gibt zwei Formen von Typerweiterungen, deren Syntax und Verhalten geringfügig voneinander abweichen. Eine systeminterne Erweiterung ist eine Erweiterung, die im gleichen Namespace oder Modul, in der gleichen Quelldatei und in der gleichen Assembly (DLL oder ausführbare Datei) angezeigt wird wie der Typ, der ausgeführt wird. Eine optionale Erweiterung ist eine Erweiterung, die außerhalb des ursprünglichen Moduls, des ursprünglichen Namespaces oder der ursprünglichen Assembly des Typs angezeigt wird, der ausgeführt wird. Systeminterne Erweiterungen werden für einen Typ angezeigt, wenn der Typ durch Reflektion untersucht wird, nicht jedoch optionale Erweiterungen. Optionale Erweiterungen müssen in Modulen enthalten sein, und sie befinden sich nur im Gültigkeitsbereich, wenn das Modul, das die Erweiterung enthält, geöffnet ist.

In der vorherigen Syntax stellt typename den Typ dar, der erweitert wird. Jeder Typ, auf den zugegriffen werden kann, ist erweiterbar, jedoch muss der Typname ein tatsächlicher Typname sein, keine Typabkürzung. Sie können in einer Typerweiterung mehrere Member definieren. Der self-identifier stellt wie bei gewöhnlichen Membern die Instanz des aufzurufenden Objekts dar.

Das end-Schlüsselwort ist in einfacher Syntax optional.

In Typerweiterungen definierte Member können genau wie andere Member eines Klassentyps verwendet werden. Wie andere Member können sie statische Member oder Instanzmember sein. Diese Methoden werden auch als Erweiterungsmethoden bezeichnet, Eigenschaften werden als Erweiterungseigenschaften bezeichnet usw. Member optionaler Erweiterungen werden in statische Member kompiliert, für die die Objektinstanz implizit als erster Parameter übergeben wird. Sie verhalten sich jedoch so, als ob sie Instanzmember oder statische Member wären, entsprechend der Art ihrer Deklarierung. Member impliziter Erweiterungen werden als Member des Typs eingeschlossen, und sie können ohne Einschränkung verwendet werden.

Erweiterungsmethoden dürfen keine virtuellen oder abstrakten Methoden sein. Sie können andere Methoden des gleichen Namens überladen, aber der Compiler bevorzugt im Fall eines mehrdeutigen Aufrufs Nicht-Erweiterungsmethoden.

Wenn für einen Typ mehrere systeminterne Typerweiterungen vorhanden sind, müssen alle Member eindeutig sein. Bei optionalen Typerweiterungen können Member in unterschiedlichen Typerweiterungen, die auf den gleichen Typ erweitert werden, die gleichen Namen aufweisen. Mehrdeutigkeitsfehler treten nur auf, wenn Clientcode zwei unterschiedliche Gültigkeitsbereiche öffnet, die die gleichen Membernamen definieren.

Im folgenden Beispiel verfügt ein Typ in einem Modul über eine systeminterne Typerweiterung. Für Clientcode außerhalb des Moduls wird die Typerweiterung in jeder Hinsicht als regulärer Member des Typs dargestellt.

module MyModule1 =

    // Define a type.
    type MyClass() =
      member this.F() = 100

    // Define type extension.
    type MyClass with
       member this.G() = 200

module MyModule2 =
   let function1 (obj1: MyModule1.MyClass) =
      // Call an ordinary method.
      printfn "%d" (obj1.F())
      // Call the extension method.
      printfn "%d" (obj1.G())

Sie können mithilfe von systeminternen Typerweiterungen die Definition eines Typs in Abschnitte aufteilen. Dies kann beim Verwalten umfangreicher Typdefinitionen hilfreich sein, um beispielsweise vom Compiler generierten Code und verfassten Code zu trennen oder um von verschiedenen Personen erstellten Code oder unterschiedlichen Funktionen zugeordneten Code in Gruppen zusammenzufassen.

Im folgenden Beispiel erweitert eine optionale Typerweiterung den System.Int32-Typ mit der Erweiterungsmethode FromString, die den statischen Member Parse aufruft. Die testFromString-Methode veranschaulicht, dass der neue Member wie ein beliebiger Instanzmember aufgerufen wird.

// Define a new member method FromString on the type Int32.
type System.Int32 with
    member this.FromString( s : string ) =
       System.Int32.Parse(s)

let testFromString str =  
    let mutable i = 0
    // Use the extension method.
    i <- i.FromString(str)
    printfn "%d" i

testFromString "500"

Der neue Instanzmember wird in IntelliSense wie eine beliebige andere Methode des Int32-Typs angezeigt, jedoch nur, wenn das Modul, das die Erweiterung enthält, geöffnet ist oder die Erweiterung aus einem anderen Grund im Gültigkeitsbereich ist.

Siehe auch

Konzepte

Member (F#)

Weitere Ressourcen

F#-Sprachreferenz