Delen via


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 xnullblijkt te zijn. Daarom is het belangrijk dat u None gebruikt wanneer een waarde nullis.

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.zeroCreategebruikt, die Unchecked.defaultofaanroept. 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 ArgumentNullExceptiongenereren, 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 NULLABLEpreprocessorrichtlijn 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.

Zie ook