Inzicht in null-baarheid
Als u een .NET-ontwikkelaar bent, is de kans groot dat u de System.NullReferenceException. Dit gebeurt tijdens de uitvoering wanneer een deductie null
wordt afgedwongen; dat wil gezegd, wanneer een variabele tijdens runtime wordt geëvalueerd, maar de variabele verwijst naar null
. Deze uitzondering is verreweg de meest voorkomende uitzondering binnen het .NET-ecosysteem. De maker van null
, Sir Tony Hoare, verwijst naar null
de 'miljard dollar fout'.
In het volgende voorbeeld wordt de FooBar
variabele toegewezen null
aan en onmiddellijk gededucteerd, waardoor het probleem wordt weergegeven:
// Declare variable and assign it as null.
FooBar fooBar = null;
// Dereference variable by calling ToString.
// This will throw a NullReferenceException.
_ = fooBar.ToString();
// The FooBar type definition.
record FooBar(int Id, string Name);
Het probleem wordt veel moeilijker te herkennen als ontwikkelaar wanneer uw apps groter en complexer worden. Het opsporen van mogelijke fouten zoals dit is een taak voor hulpprogramma's en de C#-compiler is er om u te helpen.
Null-veiligheid definiëren
De term null-veiligheid definieert een set functies die specifiek zijn voor null-typen die helpen het aantal mogelijke NullReferenceException
exemplaren te verminderen.
In het vorige FooBar
voorbeeld kunt u het NullReferenceException
volgende voorkomen door te controleren of de fooBar
variabele vóór het opnieuw uitstellen ervan was null
:
// Declare variable and assign it as null.
FooBar fooBar = null;
// Check for null
if (fooBar is not null)
{
_ = fooBar.ToString();
}
// The FooBar type definition for example.
record FooBar(int Id, string Name);
Om te helpen bij het identificeren van scenario's zoals deze, kan de compiler de intentie van uw code afleiden en het gewenste gedrag afdwingen. Dit is echter alleen wanneer een nullable context is ingeschakeld. Voordat u de null-context bespreekt, gaan we de mogelijke null-typen beschrijven.
Null-typen
Vóór C# 2.0 waren alleen verwijzingstypen null-baar. Waardetypen zoals int
of DateTime
kunnen niet zijnnull
. Als deze typen worden geïnitialiseerd zonder een waarde, vallen ze terug op hun default
waarde. In het geval van een int
, is 0
dit . Voor een DateTime
, het is DateTime.MinValue
.
Verwijzingstypen die worden geïnstantieerd zonder initiële waarden werken anders. De default
waarde voor alle referentietypen is null
.
Bekijk het volgende C#-fragment:
string first; // first is null
string second = string.Empty // second is not null, instead it's an empty string ""
int third; // third is 0 because int is a value type
DateTime date; // date is DateTime.MinValue
In het voorgaande voorbeeld:
-
first
isnull
omdat het verwijzingstypestring
is gedeclareerd, maar er geen toewijzing is gemaakt. -
second
wordt toegewezenstring.Empty
wanneer deze wordt gedeclareerd. Het object had nooit eennull
opdracht. -
third
is0
ondanks niet toegewezen. Het is eenstruct
(waardetype) en heeft eendefault
waarde van0
. -
date
is niet geïnitialiseerd, maar dedefault
waarde is System.DateTime.MinValue.
Vanaf C# 2.0 kunt u null-waardetypen definiëren met behulp van Nullable<T>
(of T?
voor afkorting). Hierdoor kunnen waardetypen null-baar zijn. Bekijk het volgende C#-fragment:
int? first; // first is implicitly null (uninitialized)
int? second = null; // second is explicitly null
int? third = default; // third is null as the default value for Nullable<Int32> is null
int? fourth = new(); // fourth is 0, since new calls the nullable constructor
In het voorgaande voorbeeld:
-
first
isnull
omdat het type null-waarde niet geïnitialiseerd is. -
second
wordt toegewezennull
wanneer deze wordt gedeclareerd. -
third
isnull
zoals dedefault
waarde voorNullable<int>
isnull
. -
fourth
is0
zoals denew()
expressie deNullable<int>
constructor aanroept enint
standaard is0
.
C# 8.0 heeft null-referentietypen geïntroduceerdnull
Misschien denkt u: "Ik dacht dat alle verwijzingstypen nullable zijn!" Je bent niet verkeerd, en dat zijn ze. Met deze functie kunt u uw intentie uitdrukken, die de compiler vervolgens probeert af te dwingen. Dezelfde T?
syntaxis geeft aan dat een verwijzingstype bedoeld is om nullable te zijn.
Bekijk het volgende C#-fragment:
#nullable enable
string first = string.Empty;
string second;
string? third;
In het voorgaande voorbeeld wordt uw intentie als volgt afgeleid door de compiler:
-
first
is nooitnull
zoals het zeker is toegewezen. -
second
mag nooit zijnnull
, ook al is het in eerste instantienull
. Evaluerensecond
voordat u een waarde toewijst, resulteert in een compilerwaarschuwing omdat deze niet geïnitialiseerd is. -
third
misschien welnull
. Het kan bijvoorbeeldnull
Een van deze variaties is acceptabel. De compiler helpt u door u te waarschuwen als u de deductiethird
zonder eerst te controleren of deze niet null is.
Belangrijk
Als u de functie voor null-verwijzingstypen wilt gebruiken zoals hierboven wordt weergegeven, moet deze zich in een null-context bevinden. Dit wordt beschreven in de volgende sectie.
Null-context
Met null-contexten kunt u nauwkeurig bepalen hoe de compiler referentietypevariabelen interpreteert. Er zijn vier mogelijke null-contexten:
-
disable
: De compiler gedraagt zich op dezelfde manier als C# 7.3 en eerder. -
enable
: De compiler maakt alle null-verwijzingsanalyse en alle taalfuncties mogelijk. -
warnings
: De compiler voert alle null-analyses uit en verzendt waarschuwingen wanneer code kan worden gedeductienull
. -
annotations
: de compiler voert geen null-analyse uit of verzendt waarschuwingen wanneer code deductienull
kan doen, maar u kunt nog steeds aantekeningen toevoegen aan uw code met behulp van null-referentietypen?
en null-forgiving-operators (!
).
Deze module heeft het bereik van disable
contexten of enable
null-contexten. Raadpleeg voor meer informatie de referentietypen Nullable: Nullable contexten.
Null-verwijzingstypen inschakelen
Voeg in het C#-projectbestand (.csproj) een onderliggend <Nullable>
knooppunt toe aan het <Project>
element (of voeg toe aan een bestaand <PropertyGroup>
). Hiermee wordt de enable
null-context toegepast op het hele project.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<!-- Omitted for brevity -->
</Project>
U kunt ook een null-context toepassen op een C#-bestand met behulp van een compilerrichtlijn.
#nullable enable
De voorgaande C#-compilerrichtlijn is functioneel gelijk aan de projectconfiguratie, maar is beperkt tot het bestand waarin deze zich bevindt. Zie Null-referentietypen voor meer informatie: Null-contexten (docs)
Belangrijk
De null-context is standaard ingeschakeld in het .csproj-bestand in alle C#-projectsjablonen die beginnen met .NET 6.0 en hoger.
Wanneer de null-context is ingeschakeld, krijgt u nieuwe waarschuwingen. Bekijk het vorige FooBar
voorbeeld, dat twee waarschuwingen bevat wanneer deze worden geanalyseerd in een nullable context:
De
FooBar fooBar = null;
regel bevat een waarschuwing voor denull
toewijzing: C# Waarschuwing CS8600: Null-letterlijke waarde of mogelijke null-waarde converteren naar niet-null-type.De
_ = fooBar.ToString();
regel heeft ook een waarschuwing. Deze keer maakt de compiler zich zorgen datfooBar
deze null kan zijn: C#-waarschuwing CS8602: Deductie van een mogelijk null-verwijzing.
Belangrijk
Er is geen gegarandeerde null-veiligheid, zelfs als u reageert en alle waarschuwingen elimineert. Er zijn enkele beperkte scenario's die de analyse van de compiler doorstaan, maar leiden tot een runtime NullReferenceException
.
Samenvatting
In deze les hebt u geleerd om een nullable context in C# in te schakelen om u te beschermen tegen NullReferenceException
. In de volgende les leert u meer over het expliciet uitdrukken van uw intentie in een nullable context.