Udostępnij za pośrednictwem


Rozszerzenia typu (F#)

Wpisz rozszerzenia umożliwiające dodawanie nowych członków do typu obiektu zdefiniowanego wcześniej.

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

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

Uwagi

Istnieją dwie formy rozszerzeń typu, różniące się nieco składnią i zachowaniem.Wewnętrzne rozszerzenie to rozszerzenie, które pojawia się w tej samej przestrzeni nazw lub module, w tym samym pliku źródłowym i w tym samym zestawie (DLL lub plik wykonywalny), gdzie typ zostanie przedłużony.Opcjonalne rozszerzenie to rozszerzenie, które pojawia się poza oryginalnym modułem, przestrzenią nazw lub zestawem typu.Wewnętrzne rozszerzenia pojawiają się na typie, gdy typ jest badany przez odbicie, ale opcjonalne rozszerzenia nie pojawiają się.Opcjonalne rozszerzenia muszą być w modułach i są wyłącznie w zakresie, gdy moduł, który zawiera rozszerzenie, jest otwarty.

W poprzedniej składni obiekt typename reprezentuje typ, który jest rozszerzany.Dowolny typ, do którego można uzyskać dostęp, może zostać przedłużony, ale nazwa typu musi być nazwą rzeczywistego typu, nie skrótem typu.Można zdefiniować wielu członków w jednym typie rozszerzenia.self-identifier reprezentuje wystąpienie wywoływanego obiektu, podobnie jak w przypadku zwykłych członków.

Słowo kluczowe end jest opcjonalne w przypadku składni lekkiej.

Elementy członkowskie zdefiniowane w rozszerzeniach typów mogą być używane tak jak inne elementy członkowskie w typie klasy.Podobnie jak inne elementy członkowskie, mogą być statyczne lub wystąpieniami elementów członkowskich.Te metody są również znane jako metody rozszerzające; właściwości są znane jako właściwości rozszerzeń, i tak dalej.Opcjonalne elementy członkowskie rozszerzeń są kompilowane do elementów statycznych, dla których wystąpienie obiektu jest przekazywane niejawnie jako pierwszy parametr.Jednak działają one tak, jakby były elementami członkowskimi wystąpień lub elementami statycznymi według tego, jak są deklarowane.Niejawne elementy członkowskie rozszerzenia są uwzględnione jako elementy członkowskie tego typu i mogą być używane bez ograniczeń.

Metody rozszerzające nie mogą być wirtualne ani abstrakcyjne.Mogą one przeciążać inne metody o tej samej nazwie, ale kompilator preferuje metod bez rozszerzeń w przypadku wywołania niejednoznacznego.

Jeśli istnieje wiele rozszerzeń typu wewnętrznego dla jednego typu, wszystkie elementy członkowskie muszą być unikatowe.Dla opcjonalnych rozszerzeń typów elementy członkowskie w innych rozszerzeniach typów tego samego typu mogą mieć takie same nazwy.Dwuznaczne błędy występują tylko wtedy, gdy kod klienta otwiera dwa różne zakresy definiujące te same nazwy składników.

W poniższym przykładzie typ w module ma rozszerzenie typu wewnętrznego.Dla kodu klienta poza modułem, rozszerzenie typu pojawia się jako regularny członek typu we wszystkich aspektach.

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())

Możesz używać rozszerzeń typu wewnętrznego, aby oddzielać definicję typu na sekcje.Może to być przydatne w zarządzaniu definicjami dużego typu, na przykład, aby oddzielnie zachować kod generowany przez kompilator i kod utworzony przez użytkownika, lub zgrupować kod utworzony przez różne osoby lub związany z różnymi funkcjami.

W poniższym przykładzie opcjonalne rozszerzenie typu rozszerza typ System.Int32 o metodę rozszerzającą FromString wywołującą statyczny element członkowski Parse.Metoda testFromString ukazuje, że nowy członek jest wywoływany podobnie jak dowolny członek wystąpienia.

// 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"

Nowy członek instancji pojawi się jak każda inna metoda typu Int32 w IntelliSense, ale tylko wtedy, gdy moduł, który zawiera rozszerzenie, jest otwarty lub znajduje się w zakresie.

Ogólne metody rozszerzające

Przed F# 3.1 kompilator F# nie obsługiwał korzystania z metod rozszerzeń stylu języka C# ze zmienną typu rodzajowego, typ tablicy, typu spoiny lub typu funkcji F# jako „tego” parametru.Język F# 3.1 obsługuje korzystanie z tych elementów członkowskich rozszerzeń.

Na przykład w kodzie języka F# 3.1 można użyć metod rozszerzających z podpisami, które przypominają następującą składnię w języku C#:

static member Method<T>(this T input, T other)

Podejście to jest szczególnie przydatne, gdy ograniczony jest parametr typu ogólnego.Ponadto można zadeklarować elementy członkowskie rozszerzeń takie jak ten w kodzie języka F# i zdefiniować dodatkowe, bogate semantycznie zestawy metod rozszerzających.W języku F# zwykle określa się elementy członkowskie rozszerzeń, co ilustruje poniższy przykład:

type seq<’T> with
    /// Repeat each element of the sequence n times
    member xs.RepeatElements(n: int) =
        seq { for x in xs do for i in 1 .. n do yield x }

Jednakże dla typu ogólnego zmienna typu nie może być ograniczona.Możesz teraz zadeklarować członek rozszerzenia C# w F# w celu obejścia tego ograniczenia.Podczas łączenia tego rodzaju deklaracji z funkcją inline F# można zaprezentować algorytmy ogólne w roli członków rozszerzenia.

Rozważyć następującą deklarację:

[<Extension>]
type ExtraCSharpStyleExtensionMethodsInFSharp () =
    [<Extension>]
    static member inline Sum(xs: seq<’T>) = Seq.sum xs

Za pomocą tej deklaracji można napisać kod, przypominający poniższy przykładowy.

let listOfIntegers = [ 1 .. 100 ]
let listOfBigIntegers = [ 1I to 100I ]
let sum1 = listOfIntegers.Sum()
let sum2 = listOfBigIntegers.Sum()

W tym kodzie ten sam ogólny kod arytmetyczny jest stosowany do list dwóch typów bez przeciążenia, definiując pojedynczy element członkowski rozszerzenia.

Zobacz też

Inne zasoby

Materiały referencyjne dotyczące języka F#

Członkowie (F#)