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 zijnnull
. - Een variabele van een verwijzingstype
T?
kan worden geïnitialiseerd ofnull
toegewezennull
, maar moet worden gecontroleerdnull
voordat de verwijzing wordt ongedaan gemaakt. - Een variabele
m
van het typeT?
wordt beschouwd als niet-null wanneer u de operator null-forgiving toepast, zoals inm!
.
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: