Handtekeningen
Een handtekeningbestand bevat informatie over de openbare handtekeningen van een set F#-programma-elementen, zoals typen, naamruimten en modules. Het kan worden gebruikt om de toegankelijkheid van deze programma-elementen op te geven.
Opmerkingen
Voor elk F#-codebestand kunt u een handtekeningbestand hebben. Dit is een bestand met dezelfde naam als het codebestand, maar met de extensie .fsi in plaats van .fs. Handtekeningbestanden kunnen ook worden toegevoegd aan de compilatie-opdrachtregel als u de opdrachtregel rechtstreeks gebruikt. Om onderscheid te maken tussen codebestanden en handtekeningbestanden, worden codebestanden soms ook wel implementatiebestanden genoemd. In een project moet het handtekeningbestand voorafgaan aan het bijbehorende codebestand.
In een handtekeningbestand worden de naamruimten, modules, typen en leden in het bijbehorende implementatiebestand beschreven. U gebruikt de informatie in een handtekeningbestand om op te geven welke onderdelen van de code in het bijbehorende implementatiebestand toegankelijk zijn vanuit code buiten het implementatiebestand en welke onderdelen intern zijn voor het implementatiebestand. De naamruimten, modules en typen die zijn opgenomen in het handtekeningbestand, moeten een subset zijn van de naamruimten, modules en typen die zijn opgenomen in het implementatiebestand. Met enkele uitzonderingen die verderop in dit onderwerp worden vermeld, worden die taalelementen die niet worden vermeld in het handtekeningbestand beschouwd als privé voor het implementatiebestand. Als er geen handtekeningbestand wordt gevonden in het project of de opdrachtregel, wordt de standaardtoegankelijkheid gebruikt.
Zie Toegangsbeheer voor meer informatie over de standaardtoegankelijkheid.
In een handtekeningbestand herhaalt u niet de definitie van de typen en de implementaties van elke methode of functie. In plaats daarvan gebruikt u de handtekening voor elke methode en functie, die fungeert als een volledige specificatie van de functionaliteit die wordt geïmplementeerd door een module of naamruimtefragment. De syntaxis voor een typehandtekening is hetzelfde als die wordt gebruikt in abstracte methodedeclaraties in interfaces en abstracte klassen, en wordt ook weergegeven door IntelliSense en door de F#-interpreter fsi.exe wanneer deze correct gecompileerde invoer weergeeft.
Als er onvoldoende informatie in de typehandtekening staat om aan te geven of een type is verzegeld of als het een interfacetype is, moet u een kenmerk toevoegen dat de aard van het type aan de compiler aangeeft. Kenmerken die u voor dit doel gebruikt, worden beschreven in de volgende tabel.
Kenmerk | Beschrijving |
---|---|
[<Sealed>] |
Voor een type dat geen abstracte leden heeft of die niet mogen worden uitgebreid. |
[<Interface>] |
Voor een type dat een interface is. |
De compiler produceert een fout als de kenmerken niet consistent zijn tussen de handtekening en de declaratie in het implementatiebestand.
Gebruik het trefwoord val
om een handtekening te maken voor een waarde of functiewaarde. Het trefwoord type
introduceert een typehandtekening.
U kunt een handtekeningbestand genereren met behulp van de --sig
compileroptie. Over het algemeen schrijft u .fsi-bestanden niet handmatig. In plaats daarvan genereert u FSI-bestanden met behulp van de compiler, voegt u ze toe aan uw project, als u er een hebt en bewerkt u ze door methoden en functies te verwijderen die u niet toegankelijk wilt maken.
Er zijn verschillende regels voor typehandtekeningen:
Type afkortingen in een implementatiebestand mogen niet overeenkomen met een type zonder afkorting in een handtekeningbestand.
Records en gediscrimineerde vakbonden moeten alle of geen van hun velden en constructors beschikbaar maken en de volgorde in de handtekening moet overeenkomen met de volgorde in het implementatiebestand. Klassen kunnen enkele, alle of geen van hun velden en methoden in de handtekening weergeven.
Klassen en structuren met constructors moeten de declaraties van hun basisklassen (de
inherits
declaratie) beschikbaar maken. Bovendien moeten klassen en structuren met constructors al hun abstracte methoden en interfacedeclaraties beschikbaar maken.Interfacetypen moeten al hun methoden en interfaces weergeven.
De regels voor waardehandtekeningen zijn als volgt:
Modifiers voor toegankelijkheid (
public
,internal
enzovoort) en deinline
enmutable
modifiers in de handtekening moeten overeenkomen met die in de implementatie.Het aantal algemene typeparameters (impliciet afgeleid of expliciet gedeclareerd) moet overeenkomen en de typen en typebeperkingen in algemene typeparameters moeten overeenkomen.
Als het
Literal
kenmerk wordt gebruikt, moet het worden weergegeven in zowel de handtekening als de implementatie, en moet dezelfde letterlijke waarde worden gebruikt voor beide.Het patroon van parameters (ook wel bekend als de arity) van handtekeningen en implementaties moet consistent zijn.
Als parameternamen in een handtekeningbestand verschillen van het bijbehorende implementatiebestand, wordt de naam in het handtekeningbestand gebruikt, wat kan leiden tot problemen bij het opsporen of profileren. Als u hiervan op de hoogte wilt worden gesteld, schakelt u waarschuwing 3218 in uw projectbestand in of bij het aanroepen van de compiler (zie
--warnon
onder Opties voor compiler).
In het volgende codevoorbeeld ziet u een voorbeeld van een handtekeningbestand met naamruimte, module, functiewaarde en typehandtekeningen, samen met de juiste kenmerken. Ook wordt het bijbehorende implementatiebestand weergegeven.
// Module1.fsi
namespace Library1
module Module1 =
val function1 : int -> int
type Type1 =
new : unit -> Type1
member method1 : unit -> unit
member method2 : unit -> unit
[<Sealed>]
type Type2 =
new : unit -> Type2
member method1 : unit -> unit
member method2 : unit -> unit
[<Interface>]
type InterfaceType1 =
abstract member method1 : int -> int
abstract member method2 : string -> unit
De volgende code toont het implementatiebestand.
namespace Library1
module Module1 =
let function1 x = x + 1
type Type1() =
member type1.method1() =
printfn "type1.method1"
member type1.method2() =
printfn "type1.method2"
[<Sealed>]
type Type2() =
member type2.method1() =
printfn "type2.method1"
member type2.method2() =
printfn "type2.method2"
[<Interface>]
type InterfaceType1 =
abstract member method1 : int -> int
abstract member method2 : string -> unit