Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Kommentar
Den här artikeln beskriver nullbara referenstyper. Du kan också deklarera nullbara värdetyper.
Använd nullbara referenstyper i kod som är i en nullbar medveten kontext. Ogiltiga referenstyper, varningar om statisk analys av null och null-förlåtande operatorn är valfria språkfunktioner. Alla är inaktiverade som standard. Du styr en nullbar kontext på projektnivå med hjälp av bygginställningar eller i kod med hjälp av pragmas.
C#-språkreferensen dokumenterar den senaste versionen av C#-språket. Den innehåller även inledande dokumentation för funktioner i offentliga förhandsversioner för den kommande språkversionen.
Dokumentationen identifierar alla funktioner som först introducerades i de tre senaste versionerna av språket eller i aktuella offentliga förhandsversioner.
Tips/Råd
Information om när en funktion först introducerades i C# finns i artikeln om språkversionshistoriken för C#.
Viktigt!
Alla projektmallar aktiverar null-kontext för projektet. Projekt som skapats med tidigare mallar inkluderar inte det här elementet, och dessa funktioner är inaktiverade om du inte aktiverar dem i projektfilen eller använder pragmas.
I en null-medveten kontext:
- Du måste initiera en variabel av en referenstyp
Tmed ett värde som inte är null och du kan aldrig tilldela ett värde som kan varanull. - Du kan initiera en variabel av en referenstyp
T?mednulleller tilldelanull, men du måste kontrollera den motnullinnan du avrefererar. - När du tillämpar operatorn null-forgiving på en variabel
mav typenT?, som im!, anses variabeln vara icke-null.
Kompilatorn tillämpar distinktionerna mellan en referenstyp som T inte kan null och en nullbar referenstyp T? med hjälp av föregående regler. En variabel av typen T och en variabel av typen T? är samma .NET-typ. I följande exempel deklareras en icke-nullbar sträng och en nullbar sträng och använder sedan operatorn null-forgiving för att tilldela ett värde till en icke-nullbar sträng:
string notNull = "Hello";
string? nullable = default;
notNull = nullable!; // null forgiveness
Variablerna notNull och nullable båda använder String typen . Eftersom de icke-nullbara och nullbara typerna båda använder samma typ kan du inte använda en nullbar referenstyp på flera platser. I allmänhet kan du inte använda en nullbar referenstyp som basklass eller implementerat gränssnitt. Du kan inte använda en nullbar referenstyp i ett testuttryck för objektskapande eller typ. Du kan inte använda en nullbar referenstyp som typ av ett medlemsåtkomstuttryck. Följande exempel visar dessa konstruktioner:
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-referenser och statisk analys
Exemplen i föregående avsnitt illustrerar typen av null-referenstyper. Nullbara referenstyper är inte nya klasstyper, utan snarare anteckningar om befintliga referenstyper. Kompilatorn använder dessa anteckningar för att hitta potentiella null-referensfel i koden. Det finns ingen körningsskillnad mellan en referenstyp som inte kan null och en referenstyp som kan ogiltigförklaras. Kompilatorn lägger inte till någon körningskontroll för referenstyper som inte går att nolla. Fördelarna finns i kompileringstidsanalysen. Kompilatorn genererar varningar som hjälper dig att hitta och åtgärda potentiella null-fel i koden. Du deklarerar din avsikt och kompilatorn varnar dig när koden bryter mot den avsikten.
Viktigt!
Ogiltiga referensanteckningar medför inte beteendeändringar, men andra bibliotek kan använda reflektion för att skapa olika körningsbeteenden för referenstyper som kan vara null- och icke-nullbara. I synnerhet läser Entity Framework Core null-attribut. Den tolkar en nullbar referens som ett valfritt värde och en icke-nullbar referens som ett obligatoriskt värde.
I en null-aktiverad kontext utför kompilatorn statisk analys på variabler av alla referenstyper, både null- och icke-nullbara. Kompilatorn spårar null-tillståndet för varje referensvariabel som antingen inte null eller kanske null. Standardtillståndet för en icke-nullbar referens är inte null. Standardtillståndet för en nullbar referens är kanske null.
Referenstyper som inte är nullbara bör alltid vara säkra att avreferera eftersom deras null-tillstånd inte är null. För att framtvinga den regeln utfärdar kompilatorn varningar om en referenstyp som inte kan nulliseras inte initieras till ett värde som inte är null. Du måste tilldela lokala variabler där du deklarerar dem. Varje fält måste tilldelas ett värde som inte är null , i en fältinitierare eller varje konstruktor. Kompilatorn utfärdar varningar när en referens som inte kan nulleras tilldelas en referens vars tillstånd kanske är null. I allmänhet är en icke-nullbar referens inte null och inga varningar utfärdas när du avreferera dessa variabler.
Kommentar
Om du tilldelar ett kanske null-uttryck till en referenstyp som inte går att nolla genererar kompilatorn en varning. Kompilatorn genererar sedan varningar för variabeln tills den har tilldelats ett uttryck som inte är null .
Du kan initiera eller tilldela null till null-referenstyper. Statisk analys måste därför fastställa att en variabel inte är null innan den derefereras. Om en nullbar referens bedöms vara kanske null, genererar tilldelning av den till en referensvariabel som inte kan null en kompilatorvarning. Följande klass visar exempel på dessa varningar:
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;
}
}
Följande kodfragment visar var kompilatorn genererar varningar när den här klassen används:
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.");
Föregående exempel visar hur kompilatorns statiska analys avgör null-tillståndet för referensvariabler. Kompilatorn tillämpar språkregler för null-kontroller och tilldelningar för att informera analysen. Kompilatorn kan inte göra antaganden om semantiken för metoder eller egenskaper. Om du anropar metoder som utför null-kontroller kan kompilatorn inte veta att dessa metoder påverkar en variabels null-tillstånd. Du kan lägga till attribut till dina API:er för att informera kompilatorn om semantiken för argument och returvärden. Många vanliga API:er i .NET-biblioteken har dessa attribut. Kompilatorn tolkar till exempel korrekt IsNullOrEmpty som en null-kontroll. Mer information om de attribut som gäller för statisk analys med null-tillstånd finns i artikeln om null-attribut.
Nullbar kontext
Den nullbara kontexten avgör hur kompilatorn hanterar anteckningar av null-referenstyp och vilka varningar som genereras vid analys av statiskt null-tillstånd. Den nullbara kontexten innehåller två flaggor: anteckningsinställningen och varningsinställningen .
Både -kommentaren och varning inställningar är inaktiverade som standard för befintliga projekt. Från och med .NET 6 (C# 10) aktiveras båda flaggorna som standard för nya projekt. Anledningen till två distinkta flaggor för den nullbara kontexten är att göra det enklare att migrera stora projekt som föregå införandet av nullbara referenstyper.
För små projekt kan du aktivera nullbara referenstyper, åtgärda varningar och fortsätta. Men för större projekt och lösningar för flera projekt kan den processen generera ett stort antal varningar. Du kan använda pragmas för att aktivera nullbara referenstyper fil för fil när du börjar använda nullbara referenstyper. De nya funktionerna som skyddar mot att kasta en System.NullReferenceException kan vara störande när de aktiveras i en befintlig kodbas:
- Alla uttryckligen inskrivna referensvariabler tolkas som icke-nullbara referenstyper.
- Innebörden av villkoret
classi generiska objekt har ändrats till en referenstyp som inte kan upphävas. - Nya varningar genereras på grund av dessa nya regler.
Den nullbara anteckningskontexten avgör kompilatorns beteende. Det finns fyra kombinationer för null-kontext inställningar:
-
båda inaktiverade: Koden är nullable-oblivious.
Inaktivera matchar beteendet innan nullbara referenstyper aktiverades, förutom att den nya syntaxen genererar varningar i stället för fel.
- Nullbara varningar är inaktiverade.
- Alla referenstypvariabler är nullbara referenstyper.
- Användning av suffixet
?för att deklarera en nullbar referenstyp ger en varning. - Du kan använda operatorn null-förlåtande,
!, men den har ingen effekt.
-
båda aktiverade: Kompilatorn aktiverar alla null-referensanalyser och alla språkfunktioner.
- Alla nya nullbara varningar är aktiverade.
- Du kan använda suffixet
?för att deklarera en nullbar referenstyp. - Referenstypvariabler utan suffixet
?är icke-nullbara referenstyper. - Nullförlåtande operatorn undertrycker varningar för en möjlig avreferering av
null.
-
varning aktiverad: Kompilatorn utför alla null-analyser och avger varningar när kod kan avreferera
null.- Alla nya nullbara varningar är aktiverade.
- Användning av suffixet
?för att deklarera en nullbar referenstyp ger en varning. - Alla referenstypvariabler tillåts vara null. Medlemmar har dock null-tillståndetnot-null vid den inledande klammerparentesen för alla metoder om de inte deklareras med suffixet
?. - Du kan använda operatorn null-förlåtande,
!.
-
kommentarer aktiverade: Kompilatorn genererar inte varningar när koden kan komma att avreferera
nulleller när du tilldelar ett uttryck som kan vara null till en variabel som inte tillåter null.- Alla nya nullable-varningar är inaktiverade.
- Du kan använda suffixet
?för att deklarera en nullbar referenstyp. - Referenstypvariabler utan suffixet
?är icke-nullbara referenstyper. - Du kan använda operatorn null-förlåtande,
!, men den har ingen effekt.
Du kan ange den nullbara kommentarskontexten och den nullbara varningskontexten för ett projekt med hjälp av elementet<Nullable> i .csproj-filen. Det här elementet konfigurerar hur kompilatorn tolkar typernas nullbarhet och vilka varningar den genererar. I följande tabell visas de tillåtna värdena och de kontexter som de anger sammanfattas.
| Context | Varningar vid avreferering | Tilldelningsvarningar | Referenstyper |
? Suffix |
! operatör |
|---|---|---|---|---|---|
disable |
Disabled | Disabled | Alla är nullbara | Skapar en varning | Har ingen effekt |
enable |
Enabled | Enabled | Ej nullbar om den inte deklareras med ? |
Deklarerar nullbar typ | Undertrycker varningar för eventuell null tilldelning |
warnings |
Enabled | Ej tillämpligt | Alla är nullbara, men medlemmar betraktas som icke-null vid inledande klammerparentes av metoder | Skapar en varning | Undertrycker varningar för eventuell null tilldelning |
annotations |
Disabled | Disabled | Ej nullbar om den inte deklareras med ? |
Deklarerar nullbar typ | Har ingen effekt |
Referenstypvariabler i kod som kompilerats i en inaktiverad kontext är nullable-oblivious. Du kan tilldela en null literal eller en kanske-null-variabel till en variabel som är nullable-oblivious. Standardtillståndet för en nullable-oblivious-variabel är dock inte null.
Välj den inställning som passar ditt projekt bäst:
- Välj inaktivera för äldre projekt som du inte vill uppdatera baserat på diagnostik eller nya funktioner.
- Välj varningar för att avgöra var koden kan utlösa System.NullReferenceExceptions. Du kan åtgärda dessa varningar innan du ändrar koden för att aktivera icke-nullbara referenstyper.
- Välj anteckningar för att uttrycka din design avsikt innan du aktiverar varningar.
- Välj aktivera för nya projekt och aktiva projekt där du vill skydda mot null-referensfel.
Exempel:
<Nullable>enable</Nullable>
Du kan också använda direktiv för att ange samma flaggor var som helst i källkoden. De här direktiven är mest användbara när du migrerar en stor kodbas.
-
#nullable enable: Anger antecknings- och varningsflaggor till aktivera. -
#nullable disable: Anger antecknings- och varningsflaggor till inaktivera. -
#nullable restore: Återställer anteckningsflaggan och varningsflaggan till projektinställningarna. -
#nullable disable warnings: Anger att varningsflaggan ska inaktiveras. -
#nullable enable warnings: Anger varningsflaggan som ska aktiveras. -
#nullable restore warnings: Återställer varningsflaggan till projektinställningarna. -
#nullable disable annotations: Anger att anteckningsflaggan ska inaktiveras. -
#nullable enable annotations: Anger anteckningsflaggan som ska aktiveras. -
#nullable restore annotations: Återställer anteckningsflaggan till projektinställningarna.
För valfri kodrad kan du ange någon av följande kombinationer:
| Varningsflagga | Anteckningsflagga | Använd |
|---|---|---|
| projektstandardinställning | projektstandardinställning | Standardinställning |
| enable | disable | Åtgärda analysvarningar |
| enable | projektstandardinställning | Åtgärda analysvarningar |
| projektstandardinställning | enable | Lägga till typanteckningar |
| enable | enable | Kod som redan har migrerats |
| disable | enable | Kommentera kod innan du åtgärdar varningar |
| disable | disable | Lägga till äldre kod i migrerat projekt |
| projektstandardinställning | disable | Sällan |
| disable | projektstandardinställning | Sällan |
Dessa nio kombinationer ger dig detaljerad kontroll över diagnostiken som kompilatorn genererar för din kod. Du kan aktivera fler funktioner i alla områden som du uppdaterar, utan att se fler varningar som du inte är redo att åtgärda ännu.
Viktigt!
Den globala nullbara kontexten gäller inte för genererade kodfiler. Under någon av strategierna inaktiveras den nullbara kontexten för alla källfiler som har markerats som genererade. Det här villkoret innebär att kompilatorn inte kommenterar några API:er i genererade filer. Kompilatorn skapar inte null-varningar för genererade filer. En fil markeras som genererad på något av följande fyra sätt:
- I .editorconfig anger du
generated_code = truei ett avsnitt som gäller för filen. - Placera
<auto-generated>eller<auto-generated/>i en kommentar överst i filen. Det kan finnas på valfri rad i kommentaren, men kommentarsblocket måste vara det första elementet i filen. - Starta filnamnet med TemporaryGeneratedFile_
- Avsluta filnamnet med .designer.cs, .generated.cs, .g.cs eller .g.i.cs.
Generatorer kan anmäla sig med hjälp #nullable av förprocessordirektivet.
Som standard inaktiveras ogiltig anteckning och varningsflaggor . Standardvärdet innebär att din befintliga kod kompileras utan ändringar och utan att några nya varningar genereras. Från och med .NET 6 innehåller nya projekt elementet <Nullable>enable</Nullable> i alla projektmallar och anger dessa flaggor till enabled.
De här alternativen innehåller två distinkta strategier för att uppdatera en befintlig kodbas för att använda null-referenstyper.
Ange den nullbara kontexten
Du kan styra den nullbara kontexten på två sätt. Lägg till projektinställningen <Nullable>enable</Nullable> på projektnivå. I en enda C#-källfil lägger du till #nullable enable pragma för att aktivera den nullbara kontexten. Mer information finns i ange en nullbar strategi. Före .NET 6 använder nya projekt standardvärdet <Nullable>disable</Nullable>. Från och med .NET 6 innehåller nya projekt elementet <Nullable>enable</Nullable> i projektfilen.
Generika
När du använder en typparameter, T, som dess nullbara motsvarighet, T?avgör argumentet för den faktiska typen hur ? tolkas. Överväg följande allmänna deklaration:
public class Box<T>
{
public T Contents { get; set; }
}
Eftersom en typparameter kan stå för antingen en referenstyp eller en värdetyp beror innebörden av T? på vilket typargument anroparen tillhandahåller. Följande regler beskriver vad T? som matchar när T det inte finns några begränsningar:
- Typargumentet är en referenstyp som inte kan ogiltigförklaras. För
Box<string>,TärstringochT?ärstring?– motsvarande null-referenstyp. - Typargumentet är en värdetyp. För
Box<int>,TärintochT?är ocksåint– samma värdetyp. Kommentaren har ingen effekt på värdetyper om inte typparametern har villkoretstruct, i vilket fallT?betyder Nullable<T> (int?). - Typargumentet kan redan vara null. För
Box<string?>,Tärstring?ochT?är fortfarandestring?. Du får inte en "dubbelt nullbar" typ.
Begränsningar begränsar vilka typargument som tillåts. De låter också kompilatorn resonera om hur T kan användas:
-
where T : classkräver en referenstyp som inte går att nolla.Box<string>tillåts.Box<string?>genererar en varning. -
where T : class?tillåter antingen en nullbar referenstyp eller en referenstyp som inte kan null- BådeBox<string>ochBox<string?>tillåts. -
where T : structkräver en värdetyp som inte kan null-värdet.Box<int>tillåts.Box<int?>Inte. Med den här begränsningenT?ärint?det i det allmänna sättet Nullable<T>– förBox<int>,T?. -
where T : notnullkräver en icke-nullbar referens- eller värdetyp.Box<string>ochBox<int>är tillåtna;Box<string?>genererar en varning. -
where T : BaseTypekräver en icke-nullbar referenstyp som härleds frånBaseType.?Lägg till (where T : BaseType?) för att tillåta nullbara härledda typer också.
Begränsningarna hjälper kompilatorn att resonera om hur en generisk typparameter används:
public static T? FirstOrDefault<T>(IEnumerable<T> source)
{
foreach (T item in source)
{
return item;
}
return default;
}
public static void RequireNotNull<T>(T value) where T : notnull
{
ArgumentNullException.ThrowIfNull(value);
}
public static void Generics()
{
string? first = FirstOrDefault<string>([]);
Console.WriteLine(first ?? "<empty>");
RequireNotNull("not null");
}
Språkspecifikation för C#
Mer information finns i avsnittet Nullable reference types (Ogiltiga referenstyper) i C#-språkspecifikationen.