Null-waarden
In dit onderwerp wordt beschreven hoe de null-waarde wordt gebruikt in F#.
Null-waarden vóór F# 9
De null-waarde wordt normaal gesproken niet gebruikt in F# voor waarden of variabelen. Null wordt echter weergegeven als een abnormale waarde in bepaalde situaties. Als een type is gedefinieerd in F#, is null niet toegestaan als een reguliere waarde, tenzij het kenmerk AllowNullLiteral wordt toegepast op het type. Als een type is gedefinieerd in een andere .NET-taal, is null een mogelijke waarde en wanneer u met dergelijke typen werkt, kan uw F#-code null-waarden tegenkomen.
Voor een type dat in F# is gedefinieerd en strikt wordt gebruikt vanuit F#, is de enige manier om rechtstreeks een null-waarde te maken met de F#-bibliotheek, het gebruik van Unchecked.defaultof of Array.zeroCreate. Voor een F#-type dat wordt gebruikt vanuit andere .NET-talen of als u dat type gebruikt met een API die niet is geschreven in F#, zoals .NET Framework, kunnen null-waarden optreden.
U kunt het option
type in F# gebruiken wanneer u mogelijk een verwijzingsvariabele met een mogelijke null-waarde in een andere .NET-taal gebruikt. In plaats van null, met een F#-option
type, gebruikt u de optiewaarde None
als er geen object is. U gebruikt de optiewaarde Some(obj)
met een object obj
wanneer er een object is. Zie Optiesvoor meer informatie. Merk op dat u er nog steeds een null
waarde in een Option kunt inpakken als x
bij Some x
null
blijkt te zijn. Daarom is het belangrijk dat u None
gebruikt wanneer een waarde null
is.
Het null
trefwoord is een geldig trefwoord in F# en u moet het gebruiken wanneer u werkt met .NET Framework-API's of andere API's die zijn geschreven in een andere .NET-taal. De twee situaties waarin u mogelijk een null-waarde nodig hebt, zijn wanneer u een .NET-API aanroept en een null-waarde als argument doorgeeft en wanneer u de retourwaarde of een uitvoerparameter uit een .NET-methodeaanroep interpreteert.
Als u een null-waarde wilt doorgeven aan een .NET-methode, gebruikt u het null
trefwoord in de aanroepende code. In het volgende codevoorbeeld ziet u dit.
open System
// Pass a null value to a .NET method.
let ParseDateTime (str: string) =
let (success, res) =
DateTime.TryParse(str, null, System.Globalization.DateTimeStyles.AssumeUniversal)
if success then Some(res) else None
Als u een null-waarde wilt interpreteren die wordt verkregen uit een .NET-methode, gebruikt u desgewenst patroonkoppeling. In het volgende codevoorbeeld ziet u hoe u patroonherkenning gebruikt om de null-waarde te interpreteren die wordt geretourneerd door ReadLine
wanneer geprobeerd wordt voorbij het einde van een invoerstroom te lezen.
// Open a file and create a stream reader.
let fileStream1 =
try
System.IO.File.OpenRead("TextFile1.txt")
with :? System.IO.FileNotFoundException ->
printfn "Error: TextFile1.txt not found."
exit (1)
let streamReader = new System.IO.StreamReader(fileStream1)
// ProcessNextLine returns false when there is no more input;
// it returns true when there is more input.
let ProcessNextLine nextLine =
match nextLine with
| null -> false
| inputString ->
match ParseDateTime inputString with
| Some(date) -> printfn "%s" (date.ToLocalTime().ToString())
| None -> printfn "Failed to parse the input."
true
// A null value returned from .NET method ReadLine when there is
// no more input.
while ProcessNextLine(streamReader.ReadLine()) do
()
Null-waarden voor F#-typen kunnen ook op andere manieren worden gegenereerd, zoals wanneer u Array.zeroCreate
gebruikt, die Unchecked.defaultof
aanroept. U moet voorzichtig zijn met dergelijke code om de null-waarden ingekapseld te houden. In een bibliotheek die alleen is bedoeld voor F#, hoeft u niet te controleren op null-waarden in elke functie. Als u een bibliotheek schrijft voor interoperation met andere .NET-talen, moet u mogelijk controles voor null-invoerparameters toevoegen en een ArgumentNullException
genereren, net zoals u doet in C# of Visual Basic-code.
U kunt de volgende code gebruiken om te controleren of een willekeurige waarde null is.
match box value with
| null -> printf "The value is null."
| _ -> printf "The value is not null."
Null-waarden beginnend met F# 9
In F# 9 worden extra mogelijkheden toegevoegd aan de taal om te gaan met referentietypen die null
als waarde kunnen hebben. Deze zijn standaard uitgeschakeld: als u ze wilt inschakelen, moet de volgende eigenschap in het projectbestand worden geplaatst:
<Nullable>enable</Nullable>
Hiermee wordt de --checknulls+
vlag doorgegeven aan de F#-compiler en wordt een NULLABLE
preprocessorrichtlijn voor de build ingesteld.
Om expliciet te kiezen voor nullbaarheid, moet een typedeclaratie worden voorzien van de nieuwe syntaxis:
type | null
Het staafsymbool |
heeft de betekenis van een logische OF in de syntaxis, waarbij twee disjuncte verzamelingen van typen worden opgebouwd: het onderliggende type en de nullable verwijzing. Dit is hetzelfde syntactische symbool dat wordt gebruikt voor het declareren van meerdere gevallen van een F#-gediscrimineerde unie: type AB = A | B
de betekenis heeft van ofwel A
, of B
.
De nullable-annotatie | null
kan worden gebruikt op alle plaatsen waar normaal gesproken een verwijzingstype wordt gebruikt:
- Velden van samenvoegtypen, recordtypen en aangepaste typen.
- Typ aliassen voor bestaande typen.
- Typeapplicaties van een generiek type.
- Expliciete typeaantekeningen om bindingen, parameters of retourtypen toe te laten.
- Typ aantekeningen voor objectprogrammeringsconstructies zoals leden, eigenschappen of velden.
type AB = A | B
type AbNull = AB | null
type RecordField = { X: string | null }
type TupleField = string * string | null
type NestedGenerics = { Z : List<List<string | null> | null> | null }
Het staafsymbool |
heeft andere gebruiksgegevens in F# die tot syntactische dubbelzinnigheden kunnen leiden. In dergelijke gevallen zijn haakjes nodig rond het nul-geannoteerde type.
// Unexpected symbol '|' (directly before 'null') in member definition
type DUField = N of string | null
Het probleem kan worden opgelost door hetzelfde type in een paar ( )
haakjes te verpakken.
type DUField = N of (string | null)
Bij gebruik in patroonkoppeling wordt |
gebruikt om verschillende patroonkoppelingsclausules te scheiden.
match x with
| ?: string | null -> ...
Dit codefragment is eigenlijk gelijk aan code die eerst een typetest uitvoert op basis van het string
type en vervolgens een afzonderlijke component heeft voor het verwerken van null:
match x with
| ?: string
| null -> ...
Belangrijk
De extra null-gerelateerde mogelijkheden zijn toegevoegd aan de taal voor de interoperabiliteitsdoeleinden. Het gebruik van | null
in F#-typemodellering wordt niet beschouwd als idiomatisch voor het aantekenen van ontbrekende informatie. Gebruik hiervoor opties (zoals hierboven beschreven). Lees meer over null-gerelateerde conventies in de stijlgids.