Megosztás a következőn keresztül:


Általánosítások

Az F#-függvényértékek, metódusok, tulajdonságok és összesítő típusok, például osztályok, rekordok és diszkriminált egyesítések általánosak lehetnek. Az általános szerkezetek legalább egy típusparamétert tartalmaznak, amelyet általában az általános szerkezet felhasználója ad meg. Az általános függvények és típusok lehetővé teszik olyan kód írását, amely különböző típusokkal működik anélkül, hogy minden típushoz meg kell ismételni a kódot. A kód általánossá tétele egyszerű lehet az F#-ban, mivel a kód gyakran implicit módon általánossá válik a fordító típuskövető és automatikus általánosítási mechanizmusai alapján.

Szemantika

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

Megjegyzések

Egy kifejezetten általános függvény vagy típus deklarációja hasonlít egy nem általános függvényhez vagy típushoz, kivéve a típusparaméterek specifikációját (és használatát) a függvény vagy típus neve utáni szögletes zárójelekben.

A deklarációk gyakran implicit módon általánosak. Ha nem adja meg teljes mértékben a függvény vagy típus megírásához használt paraméterek típusát, a fordító megpróbálja az egyes paraméterek, értékek és változók típusát az ön által írt kódból következtetni. További információ: Type Inference. Ha a típus vagy függvény kódja egyébként nem korlátozza a paraméterek típusait, a függvény vagy típus implicit módon általános. Ezt a folyamatot automatikus általánosításnak nevezik el. Az automatikus általánosításnak van néhány korlátja. Ha például az F#-fordító nem tudja kikövetkeztetni egy általános szerkezet típusait, a fordító egy olyan hibát jelez, amely az értékkorlátozás nevű korlátozásra hivatkozik. Ebben az esetben előfordulhat, hogy valamilyen típusú széljegyzetet kell hozzáadnia. Az automatikus általánosításról és az értékkorlátozásról, valamint a kód a probléma megoldásához való módosításáról az Automatikus általánosítás című témakörben talál további információt.

Az előző szintaxisban a típusparaméterek ismeretlen típusokat képviselő paraméterek vesszővel tagolt listája, amelyek mindegyike egyetlen idézőjellel kezdődik, opcionálisan egy kényszer záradékkal, amely tovább korlátozza az adott típusparaméterhez használható típusokat. A különböző típusú kényszerzárak szintaxisát és a korlátozásokkal kapcsolatos egyéb információkat a Kényszerek című témakörben talál.

A szintaxisban szereplő típusdefiníció megegyezik a nem általános típus típusdefinícióival. Tartalmazza az osztálytípus konstruktorparamétereit, az opcionális as záradékot, az egyenlőségjelet, a rekordmezőket, a inherit záradékot, a megkülönböztető egyesítések lehetőségeit, let valamint do a kötéseket, a tagdefiníciókat és minden mást, amelyet egy nem általános típusdefiníció engedélyez.

A többi szintaxiselem megegyezik a nem általános függvények és -típusokéval. Az objektumazonosító például olyan azonosító, amely magát az objektumot jelöli.

A tulajdonságok, mezők és konstruktorok nem lehetnek általánosabbak a beágyazási típusnál. Emellett a modul értékei nem lehetnek általánosak.

Implicit módon általános szerkezetek

Amikor az F#-fordító a kód típusaira következtet, automatikusan kezeli az általánosnak tekinthető függvényeket. Ha explicit módon ad meg típust, például paramétertípust, akkor megakadályozza az automatikus általánosítást.

A következő kód példában általános, annak ellenére, makeList hogy sem a paramétere, sem a paraméterei nem vannak explicit módon általánosként deklarálva.

let makeList a b = [ a; b ]

A függvény aláírása a következő.'a -> 'a -> 'a list Vegye figyelembe, hogy ab ebben a példában arra következtetünk, hogy ugyanazzal a típussal rendelkezik. Ennek az az oka, hogy ezek együtt szerepelnek a listában, és a lista minden elemének azonos típusúnak kell lennie.

A függvényeket általánossá is teheti, ha egy típusjegyzet egyetlen idézőjelszintaxisával jelzi, hogy a paramétertípus általános típusparaméter. A következő kód általános, function1 mert a paraméterek ilyen módon vannak deklarálva, típusparaméterekként.

let function1 (x: 'a) (y: 'a) = printfn "%A %A" x y

Explicit módon általános szerkezetek

A függvényeket általánossá is teheti, ha a típusparamétereket szögletes zárójelekben (<type-parameter>) explicit módon deklaráljuk. Ezt az alábbi kód szemlélteti.

let function2<'T> (x: 'T) (y: 'T) = printfn "%A, %A" x y

Általános szerkezetek használata

Általános függvények vagy metódusok használatakor előfordulhat, hogy nem kell megadnia a típusargumentumokat. A fordító típuskövetkeztetést használ a megfelelő típusargumentumok következtetéséhez. Ha továbbra is kétértelműség áll fenn, megadhat típusargumentumokat szögletes zárójelekben, vesszővel elválasztva több típusargumentumot.

Az alábbi kód az előző szakaszokban definiált függvények használatát mutatja be.

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

Megjegyzés:

Az általános típusra kétféleképpen hivatkozhat név szerint. Például kétféleképpen hivatkozhat egy olyan általános típusralist, list<int>int list amely egyetlen típusargumentumot inthasznál. Az utóbbi űrlapot hagyományosan csak beépített F# típusokkal használják, például list és option. Ha több típusargumentum is létezik, általában a szintaxist Dictionary<int, string> használja, de a szintaxist is használhatja (int, string) Dictionary.

Helyettesítő karakterek típusargumentumként

Ha meg szeretné adni, hogy a fordítónak ki kell következtetnie egy típusargumentumra, a névvel ellátott típusargumentum helyett használhatja az aláhúzásjelet vagy a helyettesítő karaktert (_). Ez az alábbi kódban jelenik meg.

let printSequence (sequence1: Collections.seq<_>) =
    Seq.iter (fun elem -> printf "%s " (elem.ToString())) sequence1

Általános típusok és függvények korlátozásai

Általános típus- vagy függvénydefiníciókban csak azokat a szerkezeteket használhatja, amelyek ismerten elérhetők az általános típusparaméteren. Ez a függvény- és metódushívások fordításkor történő ellenőrzésének engedélyezéséhez szükséges. Ha explicit módon deklarálja a típusparamétereket, explicit kényszert alkalmazhat egy általános típusparaméterre, hogy értesítse a fordítót arról, hogy bizonyos metódusok és függvények elérhetők. Ha azonban engedélyezi az F#-fordító számára az általános paramétertípusokból való következtetést, az határozza meg a megfelelő korlátozásokat. További információ: Korlátozások.

Statikusan feloldott típusparaméterek

Az F#-programokban kétféle típusparaméter használható. Az első az előző szakaszokban ismertetett általános típusparaméterek. Ez az első típusparaméter egyenértékű az olyan nyelvekben használt általános típusparaméterekkel, mint a Visual Basic és a C#. Egy másik típusparaméter az F#-ra jellemző, és statikusan feloldott típusparaméternek nevezik. Ezekről a szerkezetekről további információt a Statikusan feloldott típusparaméterek című témakörben talál.

Példák

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

Lásd még