A nullability ismertetése
Ha .NET-fejlesztő, akkor valószínűleg találkozott a System.NullReferenceException. Ez futásidőben fordul elő, amikor egy null változót elhalasztanak, vagyis amikor egy változót futásidőben értékelnek ki, de a változó a következőre nullhivatkozik: . Ez a kivétel messze a .NET-ökoszisztémában leggyakrabban előforduló kivétel. A létrehozója null, Sir Tony Hoare, utal, mint null a "milliárd dolláros hiba."
Az alábbi példában a változó hozzá FooBar van rendelve null , és azonnal dereferens lesz, így a probléma a következő:
// 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);
A problémát fejlesztőként sokkal nehezebb észlelni, ha az alkalmazások mérete és összetettsége növekszik. Az ilyen lehetséges hibák észlelése egy eszközkezelő feladat, és a C#-fordító itt segít.
Null biztonság meghatározása
A null biztonság kifejezés számát.
Az előző FooBar példát figyelembe véve elkerülheti ezt úgy NullReferenceException , hogy ellenőrzi, hogy a változó a fooBar halasztás előtt volt-e 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);
Az ilyen forgatókönyvek azonosításához a fordító képes a kód szándékára következtetni, és kikényszeríteni a kívánt viselkedést. Ez azonban csak akkor történik meg, ha engedélyezve van egy null értékű környezet . A null értékű környezet megvitatása előtt ismertessük a lehetséges null értékű típusokat.
Null értékű típusok
A C# 2.0 előtt csak a hivatkozástípusok voltak null értékűek. Az olyan értéktípusok, mint például intDateTime Ha ezeket a típusokat érték nélkül inicializálják, azok visszaállnak az értékükre default . Egy ilyen inteset esetén ez a következő 0.
DateTimeEgy, ez DateTime.MinValue.
A kezdeti értékek nélkül példányosított referenciatípusok eltérően működnek. Az default összes referenciatípus értéke .null
Vegye figyelembe a következő C#-kódrészletet:
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
Az előző példában:
-
firstazért van,nullmert a referenciatípusstringdeklarálva lett, de nem történt hozzárendelés. -
seconddeklarálásakor lesz hozzárendelvestring.Empty. Az objektumnak soha nem volt hozzárendelésenull. -
thirdannak ellenére,0hogy nincs hozzárendelve. Ez egystruct(érték típusú) ésdefaultértéke0. -
datenem inicializálódik, dedefaultértéke .System.DateTime.MinValue
A C# 2.0-tól kezdve null értékű értéktípusokat definiálhat Ez lehetővé teszi, hogy az értéktípusok null értékűek legyenek. Vegye figyelembe a következő C#-kódrészletet:
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
Az előző példában:
-
firstaz az oka,nullhogy a null értékű típus nem inicializálódott. -
seconddeklarálásakor lesz hozzárendelvenull. -
thirdértékenulladefaultNullable<int>nullkövetkező. -
fourthaz a0kifejezés, amely meghívjanew()aNullable<int>konstruktort, ésintalapértelmezés szerint az0.
A C# 8.0 null értékű referenciatípusokat vezetett Lehet, hogy arra gondol, "Azt hittem, minden referenciatípus null értékű!" Nem tévedsz, és ők is. Ez a funkció lehetővé teszi a szándék kifejezését, amelyet a fordító ezután megpróbál kikényszeríteni. Ugyanez a T? szintaxis azt fejezi ki, hogy egy hivatkozástípus null értékű.
Vegye figyelembe a következő C#-kódrészletet:
#nullable enable
string first = string.Empty;
string second;
string? third;
Az előző példában szereplő fordító a következő módon következtet a szándékra :
-
firstsoha nemmert határozottan hozzárendelték. -
secondsoha nem kell ,nullannak ellenére, hogy eredetilegnull. Az érték hozzárendelése előtt történő kiértékeléssecondfordítói figyelmeztetést eredményez, mivel az nem inicializálódik. -
thirdnulllehet . Előfordulhat például , hogy egySystem.String, de lehet, hogy anull. Bármelyik változat elfogadható. A fordító azzal segít, ha figyelmeztetést ad arról, ha a halasztásthirdnem null értékű.
Fontos
A fent látható null értékű hivatkozástípusok funkció használatához null értékű környezetben kell lennie. Ezt a következő szakaszban találja.
Null értékű környezet
A null értékű környezetek lehetővé teszik a referenciatípus-változók értelmezésének részletes szabályozását. Négy lehetséges null értékű környezet létezik:
-
disable: A fordító a C# 7.3-hoz és korábbihoz hasonlóan viselkedik. -
enable: A fordító lehetővé teszi az összes nullhivatkozás-elemzést és az összes nyelvi funkciót. -
warnings: A fordító végrehajtja az összes null elemzést, és figyelmeztetéseket ad ki, amikor a kód elferdülhetnull. -
annotations: A fordító nem végez nullelemzést, és nem ad ki figyelmeztetést, ha a kód elferdülhetnull, de a kódot null értékű hivatkozástípusokkal?és null-megbocsátó operátorokkal (!) is megjegyzésekkel láthatja el.
Ez a modul hatóköre vagy disableenable null értékű környezetekre terjed ki. További információ: Null értékű hivatkozástípusok: Null értékű környezetek.
Null értékű hivatkozástípusok engedélyezése
A C# projektfájlban (.csproj) adjon hozzá egy gyermekcsomópontot <Nullable> az <Project> elemhez (vagy fűzze hozzá egy meglévőhöz <PropertyGroup>). Ez a teljes projektre alkalmazza a enable null értékű környezetet.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<!-- Omitted for brevity -->
</Project>
Másik lehetőségként a C#-fájlok null értékű környezetét is hatókörbe helyezheti egy fordítóirányelv használatával.
#nullable enable
Az előző C#-fordító irányelv funkcionálisan egyenértékű a projektkonfigurációval, de annak a fájlnak a hatóköre, amelyben található. További információ: Null értékű referenciatípusok: Null értékű környezetek (dokumentumok)
Fontos
A null értékű környezet alapértelmezés szerint engedélyezve van a .csproj fájlban a .NET 6.0 és újabb verziójú C# projektsablonokban.
Ha a null értékű környezet engedélyezve van, új figyelmeztetések jelennek meg. Vegyük az előző FooBar példát, amely két figyelmeztetést tartalmaz null értékű környezetben történő elemzéskor:
A
FooBar fooBar = null;sor figyelmeztetést tartalmaz anullhozzárendelésre: C# FIGYELMEZTETÉS CS8600: Null literál vagy lehetséges null érték konvertálása nem null értékű típusra.A
_ = fooBar.ToString();sornak figyelmeztetése is van. A fordítófooBarezúttal null értékű lehet: C# FIGYELMEZTETÉS CS8602: Lehetséges nullhivatkozás elhalasztása.
Fontos
Nincs garantált null biztonság, még akkor sem, ha reagál az összes figyelmeztetésre, és kiküszöböli az összes figyelmeztetést. Vannak korlátozott forgatókönyvek, amelyek átadják a fordító elemzését, de futásidőt NullReferenceExceptioneredményeznek.
Összegzés
Ebben a leckében megtanulta, hogyan engedélyezhető egy null értékű környezet a C#-ban, hogy segítsen a védelemmel szemben NullReferenceException. A következő leckében többet is megtudhat arról, hogyan fejezheti ki szándékát egy null értékű környezetben.