Null-verwijzingstypen (C#-verwijzing)

Notitie

Dit artikel bevat informatie over null-verwijzingstypen. U kunt ook null-waardetypen declareren.

Nullable reference types zijn beschikbaar in code die is aangemeld voor een nullable aware context. Null-referentietypen, de waarschuwingen voor statische analyse null en de operator null-forgiving zijn optionele taalfuncties. Alles is standaard uitgeschakeld. Een nullable context wordt beheerd op projectniveau met behulp van build-instellingen of in code met behulp van pragma's.

Belangrijk

Alle projectsjablonen die beginnen met .NET 6 (C# 10) maken de null-context voor het project mogelijk. Projecten die zijn gemaakt met eerdere sjablonen bevatten dit element niet en deze functies zijn uitgeschakeld, tenzij u ze inschakelt in het projectbestand of pragma's gebruikt.

In een niet-compatibele context:

  • Een variabele van een verwijzingstype T moet worden geïnitialiseerd met niet-null en kan nooit een waarde worden toegewezen die kan zijn null.
  • Een variabele van een verwijzingstype T? kan worden geïnitialiseerd of null toegewezen null, maar moet worden gecontroleerd null voordat de verwijzing wordt ongedaan gemaakt.
  • Een variabele m van het type T? wordt beschouwd als niet-null wanneer u de operator null-forgiving toepast, zoals in m!.

Het onderscheid tussen een niet-nullable verwijzingstype T en een nullable verwijzingstype T? wordt afgedwongen door de interpretatie van de voorgaande regels van de compiler. Een variabele van het type T en een variabele van het type T? worden vertegenwoordigd door hetzelfde .NET-type. In het volgende voorbeeld worden een niet-null-tekenreeks en een null-tekenreeks declareerd en wordt vervolgens de operator null-forgiving gebruikt om een waarde toe te wijzen aan een niet-null-tekenreeks:

string notNull = "Hello";
string? nullable = default;
notNull = nullable!; // null forgiveness

De variabelen notNull en nullable worden beide vertegenwoordigd door het String type. Omdat de niet-nullbare en null-bare typen beide zijn opgeslagen als hetzelfde type, zijn er verschillende locaties waar het gebruik van een null-verwijzingstype niet is toegestaan. Over het algemeen kan een null-verwijzingstype niet worden gebruikt als basisklasse of geïmplementeerde interface. Een null-verwijzingstype kan niet worden gebruikt in een expressie voor het maken van objecten of het testen van typen. Een null-verwijzingstype kan niet het type lidtoegangsexpressie zijn. In de volgende voorbeelden ziet u de volgende constructies:

public MyClass : System.Object? // not allowed
{
}

var nullEmpty = System.String?.Empty; // Not allowed
var maybeObject = new object?(); // Not allowed
try
{
    if (thing is string? nullableString) // not allowed
        Console.WriteLine(nullableString);
} catch (Exception? e) // Not Allowed
{
    Console.WriteLine("error");
}

Null-verwijzingen en statische analyse

In de voorbeelden in de vorige sectie ziet u de aard van null-verwijzingstypen. Null-verwijzingstypen zijn geen nieuwe klassetypen, maar eerder aantekeningen op bestaande referentietypen. De compiler gebruikt deze aantekeningen om potentiële null-verwijzingsfouten in uw code te vinden. Er is geen runtime-verschil tussen een niet-null-verwijzingstype en een null-verwijzingstype. De compiler voegt geen runtimecontrole toe voor niet-nullable referentietypen. De voordelen zijn opgenomen in de analyse van de compilatietijd. De compiler genereert waarschuwingen waarmee u potentiële null-fouten in uw code kunt vinden en oplossen. U declareert uw intentie en de compiler waarschuwt u wanneer uw code die intentie schendt.

In een context met null-functionaliteit voert de compiler statische analyse uit op variabelen van elk verwijzingstype, zowel nullable als niet-nullable. De compiler houdt de null-status van elke verwijzingsvariabele bij als niet-null of misschien-null. De standaardstatus van een niet-null-verwijzing is niet null. De standaardstatus van een null-verwijzing is misschien null.

Niet-null-referentietypen moeten altijd veilig zijn om te deductie omdat de null-status niet null is. Om deze regel af te dwingen, geeft de compiler waarschuwingen uit als een niet-nullable verwijzingstype niet is geïnitialiseerd op een niet-null-waarde. Lokale variabelen moeten worden toegewezen waar ze worden gedeclareerd. Aan elk veld moet een niet-null-waarde worden toegewezen, in een veld-initialisatiefunctie of elke constructor. De compiler geeft waarschuwingen wanneer een niet-null-verwijzing wordt toegewezen aan een verwijzing waarvan de status mogelijk null is. Over het algemeen is een niet-null-verwijzing niet null en worden er geen waarschuwingen gegeven wanneer deze variabelen worden gededucteerd.

Notitie

Als u een mogelijk null-expressie toewijst aan een niet-null-referentietype , genereert de compiler een waarschuwing. De compiler genereert vervolgens waarschuwingen voor die variabele totdat deze is toegewezen aan een not-null-expressie .

Null-verwijzingstypen kunnen worden geïnitialiseerd of toegewezen aan null. Statische analyse moet daarom bepalen dat een variabele niet null is voordat deze wordt gededucteerd. Als wordt vastgesteld dat een null-verwijzing mogelijk null is, genereert het toewijzen aan een niet-null-referentievariabele een compilerwaarschuwing. In de volgende klasse ziet u voorbeelden van deze waarschuwingen:

public class ProductDescription
{
    private string shortDescription;
    private string? detailedDescription;

    public ProductDescription() // Warning! shortDescription not initialized.
    {
    }

    public ProductDescription(string productDescription) =>
        this.shortDescription = productDescription;

    public void SetDescriptions(string productDescription, string? details=null)
    {
        shortDescription = productDescription;
        detailedDescription = details;
    }

    public string GetDescription()
    {
        if (detailedDescription.Length == 0) // Warning! dereference possible null
        {
            return shortDescription;
        }
        else
        {
            return $"{shortDescription}\n{detailedDescription}";
        }
    }

    public string FullDescription()
    {
        if (detailedDescription == null)
        {
            return shortDescription;
        }
        else if (detailedDescription.Length > 0) // OK, detailedDescription can't be null.
        {
            return $"{shortDescription}\n{detailedDescription}";
        }
        return shortDescription;
    }
}

In het volgende codefragment ziet u waar de compiler waarschuwingen verzendt bij het gebruik van deze klasse:

string shortDescription = default; // Warning! non-nullable set to null;
var product = new ProductDescription(shortDescription); // Warning! static analysis knows shortDescription maybe null.

string description = "widget";
var item = new ProductDescription(description);

item.SetDescriptions(description, "These widgets will do everything.");

In de voorgaande voorbeelden ziet u hoe de statische analyse van de compiler de null-status van referentievariabelen bepaalt. De compiler past taalregels toe voor null-controles en -toewijzingen om de analyse ervan te informeren. De compiler kan geen veronderstellingen maken over de semantiek van methoden of eigenschappen. Als u methoden aanroept die null-controles uitvoeren, kan de compiler deze methoden niet kennen van invloed zijn op de null-status van een variabele. Er zijn kenmerken die u aan uw API's kunt toevoegen om de compiler te informeren over de semantiek van argumenten en retourwaarden. Deze kenmerken zijn toegepast op veel algemene API's in de .NET Core-bibliotheken. Is bijvoorbeeld IsNullOrEmpty bijgewerkt en de compiler interpreteert die methode correct als een null-controle. Zie het artikel over null-able kenmerken voor meer informatie over de kenmerken die van toepassing zijn op statische analyse met null-status.

De null-context instellen

Er zijn twee manieren om de nullable-context te beheren. Op projectniveau kunt u de <Nullable>enable</Nullable> projectinstelling toevoegen. In één C#-bronbestand kunt u de #nullable enable pragma toevoegen om de null-context in te schakelen. Zie het artikel over het instellen van een null-strategie. Vóór .NET 6 gebruiken nieuwe projecten de standaardinstelling. <Nullable>disable</Nullable> Vanaf .NET 6 bevatten nieuwe projecten het <Nullable>enable</Nullable> element in het projectbestand.

C#-taalspecificatie

Zie de volgende voorstellen voor de C#-taalspecificatie voor meer informatie:

Zie ook