Optionele referentietypen
Null-verwijzingstypen zijn een groep functies die de kans minimaliseren dat uw code ervoor zorgt dat de runtime System.NullReferenceExceptiongenereert. Drie functies waarmee u deze uitzonderingen kunt voorkomen, waaronder de mogelijkheid om expliciet een verwijzingstype te markeren als nullable:
- Verbeterde statische analyse die vaststelt of een variabele mogelijk
null
is voordat deze gedereferentieerd wordt. - Kenmerken waarmee aantekeningen worden toegevoegd aan API's, zodat de stroomanalyse de null-status bepaalt.
- Variabeleaantekeningen die ontwikkelaars gebruiken om expliciet de beoogde null-status voor een variabele te declareren.
De compiler houdt de null-status van elke expressie in uw code bij tijdens het compileren. De null-status heeft een van de volgende twee waarden:
-
not-null: De uitdrukking is bekend niet
null
te zijn. -
misschien-null: de expressie kan zijn
null
.
Variabeleaantekeningen bepalen de null-waarde van een variabele van het verwijzingstype:
-
niet-nullable: Als u een
null
waarde of een misschien-null-expressie aan de variabele toewijst, geeft de compiler een waarschuwing. Variabelen die niet-nullbaar zijn, hebben een standaard null-status van not-null. -
nullable: u kunt een
null
waarde of een misschien-null-expressie toewijzen aan de variabele. Wanneer de null-status van de variabele misschien null is, geeft de compiler een waarschuwing als u de variabele indirect gebruikt. De standaard null-status voor de variabele is misschien null.
In de rest van dit artikel wordt beschreven hoe deze drie functionaliteiten werken om waarschuwingen te genereren wanneer uw code mogelijk dereferentieert een null
waarde. Derefereren van een variabele betekent toegang krijgen tot een van zijn leden met behulp van de .
(dot) operator, zoals in het volgende voorbeeld wordt getoond:
string message = "Hello, World!";
int length = message.Length; // dereferencing "message"
Wanneer u een variabele dereferentie uitvoert waarvan de waarde null
is, gooit de runtime een System.NullReferenceException.
Op dezelfde manier kunnen waarschuwingen worden gegenereerd wanneer []
notatie wordt gebruikt voor toegang tot een lid van een object wanneer het object null
is.
using System;
public class Collection<T>
{
private T[] array = new T[100];
public T this[int index]
{
get => array[index];
set => array[index] = value;
}
}
public static void Main()
{
Collection<int> c = default;
c[10] = 1; // CS8602: Possible dereference of null
}
U krijgt meer informatie over:
- De null-statusanalyse van de compiler: hoe de compiler bepaalt of een expressie niet-null of misschien-null is.
- Kenmerken die worden toegepast op API's die meer context bieden voor de null-statusanalyse van de compiler.
- Null-variabele-annotaties die informatie verschaffen over uw intentie met betrekking tot variabelen. Aantekeningen zijn handig voor velden, parameters en retourwaarden om de standaard null-status in te stellen.
- De regels voor algemene typeargumenten. Er zijn nieuwe beperkingen toegevoegd omdat typeparameters verwijzingstypen of waardetypen kunnen zijn. Het
?
achtervoegsel wordt anders geïmplementeerd voor waarde- en referentietypen die null kunnen zijn. - De Nullable context helpt u bij het migreren van grote projecten. U kunt waarschuwingen en annotaties inschakelen in de nullcontext in delen van uw app tijdens de migratie. Nadat u meer waarschuwingen hebt adresseert, kunt u beide instellingen voor het hele project inschakelen.
Ten slotte leert u bekende valkuilen voor null-statusanalyse in struct
typen en matrices.
Deze concepten kunt u ook verkennen in onze Learn-module over null-veiligheid in C#.
Analyse van de null-toestand
Null-toestandanalyse houdt de null-toestand van verwijzingen bij. Een uitdrukking is niet-null of mogelijk-null. De compiler bepaalt dat een variabele niet null is op twee manieren:
- Aan de variabele is een waarde toegewezen die bekend staat als niet-nul.
- De variabele werd vergeleken met
null
en is sindsdien niet toegewezen.
Elke variabele die de compiler niet kan bepalen als niet-null- wordt beschouwd als misschien null-. De analyse geeft waarschuwingen in situaties waarin u per ongeluk een null
waarde derefereert. De compiler produceert waarschuwingen op basis van de null-status.
- Wanneer een variabele niet-nullis, kan die variabele veilig worden gedereferentieerd.
- Wanneer een variabele misschien-null is, moet worden gecontroleerd om ervoor te zorgen dat deze niet
null
is voordat ernaar wordt verwezen.
Kijk een naar het volgende voorbeeld:
string? message = null;
// warning: dereference null.
Console.WriteLine($"The length of the message is {message.Length}");
var originalMessage = message;
message = "Hello, World!";
// No warning. Analysis determined "message" is not-null.
Console.WriteLine($"The length of the message is {message.Length}");
// warning!
Console.WriteLine(originalMessage.Length);
In het voorgaande voorbeeld bepaalt de compiler dat message
mogelijk null is wanneer het eerste bericht wordt afgedrukt. Er is geen waarschuwing voor het tweede bericht. De laatste regel code produceert een waarschuwing omdat originalMessage
mogelijk null is. In het volgende voorbeeld ziet u een praktischer gebruik voor het doorlopen van een boomstructuur van knooppunten naar de wortel, waarbij elk knooppunt tijdens het doorlopen wordt verwerkt.
void FindRoot(Node node, Action<Node> processNode)
{
for (var current = node; current != null; current = current.Parent)
{
processNode(current);
}
}
De vorige code genereert geen waarschuwingen voor het derefereren van de variabele current
. Statische analyse bepaalt dat current
nooit wordt gedereferentieerd wanneer het mogelijk null is. De variabele current
wordt gecontroleerd op null
voordat current.Parent
wordt geopend en voordat current
wordt doorgegeven aan de ProcessNode
actie. In de vorige voorbeelden ziet u hoe de compiler de null-status voor lokale variabelen bepaalt wanneer deze wordt geïnitialiseerd, toegewezen of vergeleken met null
.
De analyse van null-status traceert niet naar aangeroepen methoden. Als gevolg hiervan kunnen velden die zijn geïnitialiseerd in een algemene helpermethode die door alle constructors wordt aangeroepen, een waarschuwing genereren met het volgende bericht:
Niet-nullable eigenschap 'name' moet een niet-nulwaarde bevatten bij het verlaten van de constructor.
U kunt deze waarschuwingen op twee manieren aanpakken: constructorkoppeling of null-attributen bij de helpermethode. In de volgende code ziet u een voorbeeld van elk. De Person
klasse maakt gebruik van een algemene constructor die wordt aangeroepen door alle andere constructors. De Student
klasse heeft een helpermethode die is voorzien van een aantekening met het System.Diagnostics.CodeAnalysis.MemberNotNullAttribute kenmerk:
using System.Diagnostics.CodeAnalysis;
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public Person() : this("John", "Doe") { }
}
public class Student : Person
{
public string Major { get; set; }
public Student(string firstName, string lastName, string major)
: base(firstName, lastName)
{
SetMajor(major);
}
public Student(string firstName, string lastName) :
base(firstName, lastName)
{
SetMajor();
}
public Student()
{
SetMajor();
}
[MemberNotNull(nameof(Major))]
private void SetMajor(string? major = default)
{
Major = major ?? "Undeclared";
}
}
De analyse van nullable-statussen en de waarschuwingen die de compiler genereert helpen je om programmeerfouten te vermijden door dereferencing van null
. Het artikel over het oplossen van nullable waarschuwingen biedt technieken voor het corrigeren van de waarschuwingen die u waarschijnlijk in uw code tegenkomt. De diagnostische gegevens die worden geproduceerd uit null-statusanalyse, zijn alleen waarschuwingen.
Kenmerken van API-handtekeningen
De analyse van null-status vereist hints van ontwikkelaars om inzicht te hebben in de semantiek van API's. Sommige API's bieden null-controles en moeten de null-status van een variabele wijzigen van misschien-null in not-null. Andere API's retourneren expressies die niet null of misschien null zijn, afhankelijk van de null-status van de invoerargumenten. Denk bijvoorbeeld aan de volgende code die een bericht in hoofdletters weergeeft:
void PrintMessageUpper(string? message)
{
if (!IsNull(message))
{
Console.WriteLine($"{DateTime.Now}: {message.ToUpper()}");
}
}
bool IsNull(string? s) => s == null;
Op basis van inspectie zou elke ontwikkelaar deze code veilig beschouwen en mag geen waarschuwingen genereren. De compiler weet echter niet dat IsNull
een null-controle biedt en geeft een waarschuwing voor de message.ToUpper()
instructie, aangezien message
als een mogelijk null-variabele wordt beschouwd. Gebruik het NotNullWhen
kenmerk om deze waarschuwing op te lossen:
bool IsNull([NotNullWhen(false)] string? s) => s == null;
Met dit kenmerk wordt de compiler geïnformeerd dat, als IsNull
false
retourneert, de parameter s
niet null is. De compiler wijzigt de null-status van message
naar not-null in het if (!IsNull(message)) {...}
blok. Er worden geen waarschuwingen gegeven.
Attributen bieden gedetailleerde informatie over de null-toestand van argumenten, retourwaarden en leden van de objectinstantie die worden gebruikt om een lid aan te roepen. De details van elk kenmerk vindt u in het taalreferentieartikel over nullable reference attributes. Vanaf .NET 5 worden alle .NET Runtime-API's geannoteerd. U verbetert de statische analyse door aantekeningen te maken bij uw API's om semantische informatie te geven over de null-status van argumenten en retourwaarden.
Aantekeningen voor null-variabelen
De analyse van null-status biedt een robuuste analyse voor lokale variabelen. De compiler heeft meer informatie van u nodig voor lidvariabelen. De compiler heeft meer informatie nodig om de null-status van alle velden in te stellen bij de openingshaak van een lid. Een van de toegankelijke constructors kan worden gebruikt om het object te initialiseren. Als een lidveld ooit de waarde null
kan krijgen, moet de compiler ervan uitgaan dat de null-state misschien null is aan het begin van elke methode.
U gebruikt aantekeningen die kunnen aangeven of een variabele een nullable verwijzingstype of een niet-nullable verwijzingstype is. Deze aantekeningen maken belangrijke instructies over de null-status voor variabelen:
-
Een verwijzing mag niet null zijn. De standaardstatus van een niet-null-referentievariabele is niet null. De compiler handhaaft regels die ervoor zorgen dat het veilig is om variabelen te derefereren zonder eerst te controleren of ze niet null zijn.
- De variabele moet worden geïnitialiseerd naar een niet-null-waarde.
- De variabele kan nooit de waarde
null
worden toegewezen. De compiler geeft een waarschuwing wanneer code een misschien null-expressie toewijst aan een variabele die niet null mag zijn.
-
Een verwijzing kan null zijn. De standaardtoestand van een nullable referentievariabele is misschien null. De compiler dwingt regels af om ervoor te zorgen dat u correct controleert op een
null
verwijzing:- De variabele kan alleen worden gedereferentieerd wanneer de compiler kan garanderen dat de waarde niet is
null
. - Deze variabelen kunnen worden geïnitialiseerd met de standaardwaarde
null
en kunnen worden toegewezen aan de waardenull
in andere code. - De compiler geeft geen waarschuwingen wanneer code een misschien-null-expressie toewijst aan een variabele die null kan zijn.
- De variabele kan alleen worden gedereferentieerd wanneer de compiler kan garanderen dat de waarde niet is
Elke niet-nulleerbare verwijzingsvariabele heeft de initiële null-status van niet-null. Elke nullable referentievariabele heeft de initiële null-status van mogelijk-null.
Er wordt een null-verwijzingstype genoteerd met dezelfde syntaxis als null-waardetypen: een ?
wordt toegevoegd aan het type variabele. De volgende variabeledeclaratie vertegenwoordigt bijvoorbeeld een variabele voor null-tekenreeksen: name
string? name;
Wanneer null-verwijzingstypen zijn ingeschakeld, is elke variabele waaraan de ?
naam van het type niet is toegevoegd, een niet-null-verwijzingstype. Dit omvat alle referentietypevariabelen in bestaande code zodra u deze functie inschakelt. Echter, impliciet getypte lokale variabelen (gedeclareerd met behulp van var
) zijn null-waarde referentietypen. Zoals in de voorgaande secties werd getoond, bepaalt statische analyse de null-status van lokale variabelen om te bepalen of ze mogelijk null zijn voordat deze worden gedereferentieerd.
Soms moet u een waarschuwing negeren wanneer u weet dat een variabele niet null is, maar de compiler bepaalt dat de null-status mogelijk null is. U gebruikt de null-vergevingsgezinde operator!
na een variabelenaam om af te dwingen dat de null-statusniet-null is. Als u bijvoorbeeld weet dat de name
variabele niet null
is, maar de compiler een waarschuwing geeft, kunt u de volgende code schrijven om de analyse van de compiler te overschrijven:
name!.Length;
Null-referentietypen en null-waardetypen bieden een vergelijkbaar semantisch concept: een variabele kan een waarde of object vertegenwoordigen, of die variabele kan zijn null
. Null-verwijzingstypen en null-waardetypen worden echter anders geïmplementeerd: null-waardetypen worden geïmplementeerd met behulp van System.Nullable<T>en null-verwijzingstypen worden geïmplementeerd door kenmerken die door de compiler worden gelezen. En beide worden bijvoorbeeld string?
string
vertegenwoordigd door hetzelfde type: System.String.
int?
En int
worden echter vertegenwoordigd door System.Nullable<System.Int32>
respectievelijkSystem.Int32.
Nullable-referentietypen zijn een compile-tijdfunctie. Dit betekent dat aanroepers waarschuwingen kunnen negeren en opzettelijk null
gebruiken als argument voor een methode die een niet-nullbare verwijzing verwacht. Auteurs van bibliotheken moeten runtimecontroles opnemen op basis van null-argumentwaarden. De ArgumentNullException.ThrowIfNull optie is de voorkeursoptie voor het controleren van een parameter op null tijdens runtime. Bovendien is het runtimegedrag van een programma dat gebruikmaakt van null-aantekeningen hetzelfde als alle null-aantekeningen (?
en !
), worden verwijderd. Hun enige doel is het uitdrukken van ontwerpintentie en het verstrekken van informatie voor null-statusanalyse.
Belangrijk
Het inschakelen van ondersteuning voor nullable annotaties kan wijzigen hoe Entity Framework Core bepaalt of een dataveld vereist is. Meer informatie vindt u in het artikel over de basisprincipes van Entity Framework Core: Werken met Nullable Reference Types.
Generics
Gedetailleerde regels zijn vereist om generics te beheren voor elke typeparameter T?
T
. De regels zijn noodzakelijkerwijs gedetailleerd vanwege de geschiedenis en de verschillende implementatie voor een type null-waarde en een null-referentietype.
Null-waardetypen worden geïmplementeerd met behulp van de System.Nullable<T> structuur.
Nullable referentietypen worden geïmplementeerd als typeaantekeningen die semantische regels aan de compiler verschaffen.
- Als het typeargument
T
een verwijzingstype is, verwijstT?
naar het overeenkomstige nullbare verwijzingstype. AlsT
bijvoorbeeld eenstring
is, dan isT?
eenstring?
. - Als het typeargument
T
voor een waardetype is,T?
verwijst u naar hetzelfde waardetype,T
. AlsT
bijvoorbeeld eenint
is, isT?
ook eenint
. - Als het typeargument voor
T
een nullable referentietype is, verwijstT?
naar datzelfde nullable referentietype. AlsT
eenstring?
is, dan isT?
ook eenstring?
. - Als het typeargument voor
T
een nulwaardige waarde is, verwijstT?
naar datzelfde nulwaardige type. AlsT
eenint?
is, dan isT?
ook eenint?
.
Voor retourwaarden is T?
dit gelijk aan [MaybeNull]T
; voor argumentwaarden is T?
dit gelijk aan [AllowNull]T
. Zie het artikel over kenmerken voor analyse van null-status in de taalverwijzing voor meer informatie.
U kunt verschillende gedragingen opgeven met behulp van beperkingen:
- De
class
beperking betekent dat ditT
een niet-null-verwijzingstype moet zijn (bijvoorbeeldstring
). De compiler produceert een waarschuwing als u een null-verwijzingstype gebruikt, zoalsstring?
voorT
. - De
class?
beperking betekent datT
een verwijzingstype moet zijn, ofwel niet-nullable (string
) of een nullable verwijzingstype (bijvoorbeeldstring?
). Wanneer de typeparameter een nullable verwijzingstype is, zoalsstring?
, verwijst een expressie vanT?
naar hetzelfde nullable verwijzingstype, zoalsstring?
. - De
notnull
beperking betekent dat ditT
een niet-null-verwijzingstype of een niet-null-waardetype moet zijn. Als u een null-verwijzingstype of een null-waardetype voor de typeparameter gebruikt, genereert de compiler een waarschuwing. Bovendien, wanneerT
een waardetype is, is de retourwaarde dat waardetype, niet het overeenkomstige nulbare waardetype.
Deze beperkingen helpen de compiler meer informatie te geven over hoe T
wordt gebruikt. Dit helpt wanneer ontwikkelaars het type T
kiezen en het biedt betere null-statusanalyse wanneer een exemplaar van het generieke type wordt gebruikt.
Null-context
De nullable context bepaalt hoe nullable referentietype-annotaties worden verwerkt en welke waarschuwingen worden gegenereerd door statische nulstatusanalyse. De null-context bevat twee vlaggen: de aantekeningsinstelling en de waarschuwingsinstelling.
Zowel de aantekening als waarschuwing instellingen zijn standaard uitgeschakeld voor bestaande projecten. Vanaf .NET 6 (C# 10) zijn beide vlaggen standaard ingeschakeld voor nieuwe projecten. De reden voor twee afzonderlijke vlaggen voor de nulbare context is om het eenvoudiger te maken om grote projecten te migreren die dateren van vóór de introductie van nulbare referentietypen.
Voor kleine projecten kun je nulbare referentietypen inschakelen, waarschuwingen corrigeren en doorgaan. Voor grotere projecten en oplossingen voor meerdere projecten kan dit echter een groot aantal waarschuwingen genereren. U kunt pragma's gebruiken om nullable-referentietypes per bestand in te schakelen wanneer u begint met het gebruik van nullable-referentietypes. De nieuwe functies die beschermen tegen het genereren van een System.NullReferenceException bestand, kunnen storend zijn wanneer ze zijn ingeschakeld in een bestaande codebasis:
- Alle expliciet getypte referentievariabelen worden geïnterpreteerd als niet-nullable verwijzingstypen.
- De betekenis van de
class
beperking in generieke types is gewijzigd naar een niet-nulleerbare referentietype. - Er worden nieuwe waarschuwingen gegenereerd vanwege deze nieuwe regels.
De nullable-annotatiecontext bepaalt het gedrag van de compiler. Er zijn vier combinaties voor de nullable-context-instellingen:
-
beide uitgeschakeld: De code is nullable-onbewust.
Uitschakelen komt overeen met het gedrag voordat null-verwijzingstypen zijn ingeschakeld, behalve dat de nieuwe syntaxis waarschuwingen produceert in plaats van fouten.
- Null-waarschuwingen zijn uitgeschakeld.
- Alle referentietypevariabelen zijn null-referentietypen.
- Het gebruik van het
?
achtervoegsel om een nullable verwijzingstype te declareren, produceert een waarschuwing. - U kunt de operator null forgiving gebruiken,
!
maar dit heeft geen effect.
-
beide ingeschakeld: de compiler schakelt alle null-referentieanalyse en alle taalfuncties in.
- Alle nieuwe null-bare waarschuwingen zijn ingeschakeld.
- U kunt het
?
achtervoegsel gebruiken om een null-verwijzingstype te declareren. - Verwijzingstypevariabelen zonder achtervoegsel
?
zijn niet-nullbare verwijzingstypen. - De null forgiving operator onderdrukt waarschuwingen voor een mogelijke dereferentie van
null
.
-
waarschuwing ingeschakeld: de compiler voert alle null-analyse uit en geeft waarschuwingen wanneer de code mogelijk dereferentie naar
null
.- Alle nieuwe null-bare waarschuwingen zijn ingeschakeld.
- Het gebruik van het
?
achtervoegsel om een nullable verwijzingstype te declareren, produceert een waarschuwing. - Alle referentietypevariabelen mogen null zijn. Leden hebben echter de null-statusnot-null bij de accolade openen van alle methoden, tenzij ze zijn gedeclareerd met het
?
achtervoegsel. - U kunt de null-forgiving operator
!
gebruiken.
-
aantekeningen ingeschakeld: de compiler geeft geen waarschuwingen af wanneer code mogelijk dereferentiert
null
, of wanneer u een mogelijk-null-expressie toewijst aan een niet-null-variabele.- Alle nieuwe nullable-waarschuwingen zijn uitgeschakeld.
- U kunt het
?
achtervoegsel gebruiken om een null-verwijzingstype te declareren. - Verwijzingstypevariabelen zonder achtervoegsel
?
zijn niet-nullbare verwijzingstypen. - U kunt de operator null forgiving gebruiken,
!
maar dit heeft geen effect.
De nullable-annotatiecontext en de nullable waarschuwingscontext kunnen worden ingesteld voor een project met behulp van het <Nullable>
-element in uw .csproj-bestand. Dit element configureert hoe de compiler de null-waarde van typen interpreteert en welke waarschuwingen worden verzonden. In de volgende tabel worden de toegestane waarden weergegeven en wordt samengevat in welke contexten ze gebruikt kunnen worden.
Context | Dereference-waarschuwingen | Toewijzingswaarschuwingen | Verwijzingstypen |
? achtervoegsel |
! bediener |
---|---|---|---|---|---|
disable |
Uitgeschakeld | Uitgeschakeld | Alle zijn optioneel aanpasbaar | Hiermee wordt een waarschuwing gegenereerd | Heeft geen effect |
enable |
Ingeschakeld | Ingeschakeld | Niet-nullable tenzij gedeclareerd met ? |
Verklaart een nullable type | Onderdrukt waarschuwingen voor mogelijke null toewijzingen |
warnings |
Ingeschakeld | Niet van toepassing | Alle zijn nullable, maar leden worden beschouwd als niet-null bij het openen van methoden. | Hiermee wordt een waarschuwing gegenereerd | Onderdrukt waarschuwingen voor mogelijke null toewijzing |
annotations |
Uitgeschakeld | Uitgeschakeld | Niet-nullable tenzij gedeclareerd met ? |
Declareert nulwaarde-gegevenstype | Heeft geen effect |
Variabelen voor verwijzingstypen in code die zijn gecompileerd in een uitgeschakelde context, zijn null-vergetelbaar. U kunt een null
letterlijke waarde of een misschien null-variabele toewijzen aan een variabele die null-vergetelbaar is. De standaardstatus van een nullable-oblivious variabele is echter niet-null.
U kunt kiezen welke instelling het beste is voor uw project:
- Kies uitschakelen voor verouderde projecten die u niet wilt bijwerken op basis van diagnostische gegevens of nieuwe functies.
- Kies waarschuwingen om te bepalen waar uw code System.NullReferenceExceptions kan genereren. U kunt deze waarschuwingen aanpakken voordat u code wijzigt om niet-opnullbare verwijzingstypen in te schakelen.
- Kies aantekeningen om uw ontwerpintentie uit te drukken voordat u waarschuwingen inschakelt.
- Kies Inschakelen voor nieuwe projecten en actieve projecten waarvoor u wilt beveiligen tegen null-referentie-uitzonderingen.
Voorbeeld:
<Nullable>enable</Nullable>
U kunt ook instructies gebruiken om dezelfde vlaggen overal in uw broncode in te stellen. Deze instructies zijn het handigst wanneer u een grote codebasis migreert.
-
#nullable enable
: hiermee stelt u de aantekening en waarschuwingsvlaggen in op inschakelen. -
#nullable disable
: Hiermee stelt u de annotatie- en waarschuwingsvlaggen in om uit te schakelen. -
#nullable restore
: hiermee herstelt u de aantekeningsvlag en waarschuwingsvlag naar de projectinstellingen. -
#nullable disable warnings
: stel de waarschuwingsvlag in op uitschakelen. -
#nullable enable warnings
: Stel de waarschuwingsvlag in op Inschakelen. -
#nullable restore warnings
: hiermee herstelt u de waarschuwingsvlag in de projectinstellingen. -
#nullable disable annotations
: stel de annotatievlag in op om uit te schakelen. -
#nullable enable annotations
: stel de aantekeningsvlag in op omin te schakelen. -
#nullable restore annotations
: hiermee herstelt u de aantekeningsvlag naar de projectinstellingen.
Voor elke regel code kunt u een van de volgende combinaties instellen:
Waarschuwingsvlag | Aantekeningsvlag | Gebruik |
---|---|---|
standaardproject | standaardproject | Standaard |
inschakelen | uitschakelen | Analysewaarschuwingen oplossen |
inschakelen | standaardproject | Analysewaarschuwingen oplossen |
standaardproject | inschakelen | Typeaantekeningen toevoegen |
inschakelen | inschakelen | Code is al gemigreerd |
uitschakelen | inschakelen | Aantekeningen toevoegen aan code voordat waarschuwingen worden opgelost |
uitschakelen | uitschakelen | Verouderde code toevoegen aan gemigreerd project |
standaardproject | uitschakelen | Zelden |
uitschakelen | standaardproject | Zelden |
Deze negen combinaties bieden u nauwkeurige controle over de diagnostische gegevens die de compiler verzendt voor uw code. U kunt meer functies inschakelen in elk gebied dat u bijwerkt, zonder dat u meer waarschuwingen ziet die u nog niet kunt adresseren.
Belangrijk
De globale null-context is niet van toepassing op gegenereerde codebestanden. Onder een van beide strategieën wordt de null-context uitgeschakeld voor elk bronbestand dat is gemarkeerd als gegenereerd. Dit betekent dat api's in gegenereerde bestanden niet worden geannoteerd. Er worden geen nulbare waarschuwingen gegenereerd voor gegenereerde bestanden. Er zijn vier manieren waarop een bestand wordt gemarkeerd als gegenereerd:
- Geef
generated_code = true
in de .editorconfig een sectie op die van toepassing is op dat bestand. - Plaats
<auto-generated>
of<auto-generated/>
in een opmerking boven aan het bestand. Het kan op elke regel in die opmerking staan, maar het opmerkingenblok moet het eerste element in het bestand zijn. - Start de bestandsnaam met TemporaryGeneratedFile_
- Beëindig de bestandsnaam met .designer.cs, .generated.cs, .g.cs of .g.i.cs.
Generatoren kunnen zich aanmelden met behulp van de #nullable
preprocessorrichtlijn.
Standaard zijn null-aantekeningen en waarschuwingsvlaggen uitgeschakeld. Dit betekent dat uw bestaande code wordt gecompileerd zonder wijzigingen en zonder nieuwe waarschuwingen te genereren. Vanaf .NET 6 bevatten nieuwe projecten het element <Nullable>enable</Nullable>
in alle projectsjablonen, waarbij u deze vlaggen instelt op ingeschakelde.
Deze opties bieden twee verschillende strategieën voor het bijwerken van een bestaande codebasis voor het gebruik van null-referentietypen.
Bekende valkuilen
Arrays en structs die referentietypen bevatten, zijn bekende valkuilen in nullable referenties en de statische analyse die null-veiligheid bepaalt. In beide situaties kan een niet-null-bare verwijzing worden geïnitialiseerd met null
, zonder dat er waarschuwingen worden gegenereerd.
Structuren
Met een struct die niet-nullbare verwijzingstypen bevat, kan deze zonder waarschuwingen worden toegewezen default
. Kijk een naar het volgende voorbeeld:
using System;
#nullable enable
public struct Student
{
public string FirstName;
public string? MiddleName;
public string LastName;
}
public static class Program
{
public static void PrintStudent(Student student)
{
Console.WriteLine($"First name: {student.FirstName.ToUpper()}");
Console.WriteLine($"Middle name: {student.MiddleName?.ToUpper()}");
Console.WriteLine($"Last name: {student.LastName.ToUpper()}");
}
public static void Main() => PrintStudent(default);
}
In het voorgaande voorbeeld is er geen waarschuwing in PrintStudent(default)
, terwijl de niet-nullbare verwijzingstypen FirstName
en LastName
toch null zijn.
Een andere veelvoorkomende zaak is wanneer u met algemene structs te maken krijgt. Kijk een naar het volgende voorbeeld:
#nullable enable
public struct S<T>
{
public T Prop { get; set; }
}
public static class Program
{
public static void Main()
{
string s = default(S<string>).Prop;
}
}
In het voorgaande voorbeeld is de eigenschap Prop
null
tijdens de uitvoering. Dit wordt zonder waarschuwingen toegewezen aan een niet-nullable string.
Reeksen
Arrays zijn ook een bekende valkuil in nullable-referentietypen. Bekijk het volgende voorbeeld dat geen waarschuwingen produceert:
using System;
#nullable enable
public static class Program
{
public static void Main()
{
string[] values = new string[10];
string s = values[0];
Console.WriteLine(s.ToUpper());
}
}
In het voorgaande voorbeeld toont de declaratie van de matrix dat deze niet-nullable tekenreeksen bevat, terwijl de elementen allemaal zijn geïnitialiseerd tot null
. Vervolgens wordt aan de variabele s
een null
waarde toegewezen (het eerste element van de matrix). Ten slotte wordt de variabele s
gedereferentieerd, wat een runtime-uitzondering veroorzaakt.
Constructeurs
Constructor van een klasse roept nog steeds de finalizer aan, zelfs wanneer er een uitzondering is opgetreden door die constructor.
In het volgende voorbeeld ziet u dat gedrag:
public class A
{
private string _name;
private B _b;
public A(string name)
{
ArgumentNullException.ThrowIfNullOrEmpty(name);
_name = name;
_b = new B();
}
~A()
{
Dispose();
}
public void Dispose()
{
_b.Dispose();
GC.SuppressFinalize(this);
}
}
public class B: IDisposable
{
public void Dispose() { }
}
public void Main()
{
var a = new A(string.Empty);
}
In het voorgaande voorbeeld wordt de System.NullReferenceException gegenereerd wanneer _b.Dispose();
wordt uitgevoerd, als de parameter name
is null
. De aanroep van _b.Dispose();
zal nooit worden gegooid wanneer de constructor is voltooid. Er is echter geen waarschuwing uitgegeven door de compiler, omdat statische analyse niet kan bepalen of een methode (zoals een constructor) wordt voltooid zonder dat er een runtime-uitzondering wordt gegenereerd.