Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
F#-functiewaarden, methoden, eigenschappen en statistische typen, zoals klassen, records en gediscrimineerde samenvoegingen, kunnen algemeen zijn. Algemene constructies bevatten ten minste één typeparameter, die meestal wordt geleverd door de gebruiker van de algemene constructie. Met algemene functies en typen kunt u code schrijven die met verschillende typen werkt zonder dat u de code voor elk type hoeft te herhalen. Het maken van uw code algemeen kan eenvoudig zijn in F#, omdat uw code vaak impliciet wordt afgeleid om algemeen te zijn door de typedeductie en automatische generalisatiemechanismen van de compiler.
Syntaxis
// 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
Opmerkingen
De declaratie van een expliciet generieke functie of type lijkt veel op die van een niet-generieke functie of type, met uitzondering van de specificatie (en het gebruik) van de typeparameters, tussen punthaken na de functie of typenaam.
Declaraties zijn vaak impliciet algemeen. Als u niet volledig het type opgeeft van elke parameter die wordt gebruikt voor het opstellen van een functie of type, probeert de compiler het type van elke parameter, waarde en variabele af te stellen van de code die u schrijft. Zie Type deductie voor meer informatie. Als de code voor uw type of functie de typen parameters niet anders beperkt, is de functie of het type impliciet algemeen. Dit proces heet automatische generalisatie. Er gelden enkele limieten voor automatische generalisatie. Als de F#-compiler bijvoorbeeld de typen voor een algemene constructie niet kan afleiden, rapporteert de compiler een fout die verwijst naar een beperking genaamd de waardebeperking. In dat geval moet u mogelijk enkele typeaantekeningen toevoegen. Zie Automatische generalisatie voor meer informatie over automatische generalisatie en de waardebeperking en het wijzigen van uw code om het probleem op te lossen.
In de vorige syntaxis is type-parameters een door komma's gescheiden lijst met parameters die onbekende typen vertegenwoordigen, die elk beginnen met één aanhalingsteken, optioneel met een beperkingscomponent die verder beperkt welke typen voor die typeparameter kunnen worden gebruikt. Zie Beperkingen voor de syntaxis voor beperkingsclausules van verschillende soorten en andere informatie over beperkingen.
De typedefinitie in de syntaxis is hetzelfde als de typedefinitie voor een niet-algemeen type. Het bevat de constructorparameters voor een klassetype, een optionele as component, het gelijksymbool, de recordvelden, de inherit component, de keuzes voor een gediscrimineerde samenvoeging en letdo bindingen, liddefinities en alles wat anders is toegestaan in een niet-algemene typedefinitie.
De andere syntaxiselementen zijn hetzelfde als die voor niet-algemene functies en typen. Object-id is bijvoorbeeld een id die het betreffende object zelf vertegenwoordigt.
Eigenschappen, velden en constructors kunnen niet meer algemeen zijn dan het type omsluiten. Waarden in een module kunnen ook niet algemeen zijn.
Impliciet algemene constructies
Wanneer de F#-compiler de typen in uw code afgeeft, worden automatisch alle functies behandeld die algemeen kunnen zijn. Als u een type expliciet opgeeft, zoals een parametertype, voorkomt u automatische generalisatie.
In het volgende codevoorbeeld makeList is dit algemeen, ook al worden deze noch de parameters expliciet als algemeen gedeclareerd.
let makeList a b = [ a; b ]
De handtekening van de functie wordt afgeleid.'a -> 'a -> 'a list Houd er rekening mee dat a en b in dit voorbeeld worden afgeleid dat ze hetzelfde type hebben. Dit komt doordat ze samen in een lijst worden opgenomen en alle elementen van een lijst van hetzelfde type moeten zijn.
U kunt een functie ook algemeen maken met behulp van de syntaxis van één aanhalingsteken in een typeaantekening om aan te geven dat een parametertype een algemene typeparameter is. In de volgende code function1 is algemeen omdat de parameters op deze manier worden gedeclareerd, zoals typeparameters.
let function1 (x: 'a) (y: 'a) = printfn "%A %A" x y
Expliciet algemene constructies
U kunt een functie ook algemeen maken door expliciet de typeparameters in punthaken (<type-parameter>) te declareren. De volgende code illustreert dit.
let function2<'T> (x: 'T) (y: 'T) = printfn "%A, %A" x y
Algemene constructies gebruiken
Wanneer u algemene functies of methoden gebruikt, hoeft u mogelijk niet de typeargumenten op te geven. De compiler gebruikt typedeductie om de juiste typeargumenten af te stellen. Als er nog steeds dubbelzinnigheid is, kunt u typeargumenten opgeven tussen punthaken en meerdere typeargumenten scheiden met komma's.
De volgende code toont het gebruik van de functies die in de vorige secties zijn gedefinieerd.
// 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
Opmerking
Er zijn twee manieren om te verwijzen naar een algemeen type op naam. En zijn bijvoorbeeld list<int> twee manieren om te verwijzen naar een algemeen type list met één typeargumentint.int list De laatste vorm wordt conventioneel alleen gebruikt met ingebouwde F#-typen zoals list en option. Als er meerdere typeargumenten zijn, gebruikt u normaal gesproken de syntaxis Dictionary<int, string> , maar kunt u ook de syntaxis (int, string) Dictionarygebruiken.
Jokertekens als typeargumenten
Als u wilt opgeven dat een typeargument moet worden afgeleid door de compiler, kunt u het onderstrepingsteken of jokerteken (_) gebruiken in plaats van een benoemd typeargument. Dit wordt weergegeven in de volgende code.
let printSequence (sequence1: Collections.seq<_>) =
Seq.iter (fun elem -> printf "%s " (elem.ToString())) sequence1
Beperkingen in algemene typen en functies
In een algemene type- of functiedefinitie kunt u alleen de constructies gebruiken die bekend zijn als beschikbaar zijn voor de algemene typeparameter. Dit is vereist om de verificatie van functie- en methode-aanroepen tijdens het compileren in te schakelen. Als u uw typeparameters expliciet declareert, kunt u een expliciete beperking toepassen op een algemene typeparameter om de compiler op de hoogte te stellen dat bepaalde methoden en functies beschikbaar zijn. Als u echter de F#-compiler toestaat om uw algemene parametertypen af te leiden, wordt de juiste beperkingen voor u bepaald. Zie Beperkingen voor meer informatie.
Parameters voor statisch opgelost type
Er zijn twee soorten parameters die kunnen worden gebruikt in F#-programma's. De eerste zijn algemene typeparameters van het type dat in de vorige secties wordt beschreven. Dit eerste type parameter is gelijk aan de algemene typeparameters die worden gebruikt in talen zoals Visual Basic en C#. Een ander typeparameter is specifiek voor F# en wordt een statisch opgeloste typeparameter genoemd. Zie Statisch opgeloste typeparameters voor meer informatie over deze constructies.
Voorbeelden
// 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