Null atanabilirliği anlama

Tamamlandı

.NET geliştiricisiyseniz, büyük olasılıkla ile karşılaşmışsınızdır System.NullReferenceException. Bu, çalışma zamanında bir başvurulmadığında null , yani bir değişken çalışma zamanında değerlendirildiğinde, ancak değişkenine nullbaşvurduğunda oluşur. Bu özel durum açık arayla .NET ekosisteminde en sık karşılaşılan özel durumdur. Sör Tony Hoare'nin yaratıcısı null"milyar dolarlık hata" olarak adlandırılır null .

Aşağıdaki örnekte değişkenine FooBar atanır null ve hemen başvurulmaz ve bu nedenle sorun sergilenir:

// 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);

Uygulamalarınızın boyutu ve karmaşıklığı arttığında sorun geliştirici olarak fark etmek çok daha zor hale gelir. Bunun gibi olası hataları tespit etmek bir araç işidir ve C# derleyicisi yardımcı olmak için buradadır.

Null güvenlik tanımlama

Null güvenlik terimi, olası oluşum sayısını azaltmaya yardımcı olan NullReferenceException özgü bir özellik kümesini tanımlar.

Önceki FooBar örneği göz önünde bulundurarak değişkenin NullReferenceException başvuruyu fooBar kaldırmadan önce olup olmadığını null denetleyerek öğesini önleyebilirsiniz:

// 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);

Derleyici, bunun gibi senaryoların tanımlanmasına yardımcı olmak için kodunuzun amacını çıkarsayarak istenen davranışı uygulayabilir. Ancak, bu yalnızca null değeri alabilir bir bağlam etkinleştirildiğinde olur. Null atanabilir bağlamı tartışmadan önce, olası null atanabilir türleri açıklayalım.

Boş değer atanabilir tipler

C# 2.0'da yalnızca başvuru türleri null atanabilirdi. gibi int veya DateTime değer türleri olamazdınull. Bu türler bir değer olmadan başlatılırsa, değerlerine default geri dönerler. durumunda int, bu olur 0. DateTimebir için, bu DateTime.MinValue.

Başlangıç değerleri olmadan örnek olarak örneklene başvuru türleri farklı çalışır. Tüm başvuru türlerinin default değeri olur null.

Aşağıdaki C# kod parçacığını göz önünde bulundurun:

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

Yukarıdaki örnekte:

  • first bunun null nedeni, başvuru türünün string bildirildiği ancak atama yapılmadığıdır.
  • second bildirildiğinde atanır string.Empty . Nesnenin hiç ataması null olmadı.
  • third atanmamış olmasına 0 rağmen. Bu bir struct (değer türü) ve değerine defaultsahiptir0.
  • date başlatılmamış, ancak default değeri şeklindedir System.DateTime.MinValue.

C# 2.0'dan başlayarak, kullanarak (veya kısaltma için) null atanabilir değer türleri Nullable<T>T?. Bu, değer türlerinin null atanabilir olmasını sağlar. Aşağıdaki C# kod parçacığını göz önünde bulundurun:

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

Yukarıdaki örnekte:

  • first , null null atanabilir değer türünün başlatılmamış olmasıdır.
  • second bildirildiğinde atanır null .
  • thirddeğeri olarak nulldefaultNullable<int> değeridir.null
  • fourth , 0 ifadenin new() oluşturucuyu çağırdığı Nullable<int> ve int varsayılan olarak olduğu şekildedir 0 .

C# 8.0, bir başvuru türünün veya her zaman olmayan bir başvuru türünün "Tüm başvuru türlerinin null atanabilir olduğunu düşünmüştüm!" diye düşünüyor olabilirsiniz. Sen haksız değilsin, onlar da. Bu özellik, derleyicinin zorlamaya çalıştığı amacınızı ifade etmenizi sağlar. Aynı T? söz dizimi, başvuru türünün null atanabilir olmasını hedeflediğini ifade eder.

Aşağıdaki C# kod parçacığını göz önünde bulundurun:

#nullable enable

string first = string.Empty;
string second;
string? third;

Yukarıdaki örnekte, derleyici amacınızı aşağıdaki gibi çıkarsar:

  • first aslanull değildir, çünkü kesinlikle atanmıştır.
  • second olmamalıdırnull. second Değer atamadan önce değerlendirme, başlatılmamış olduğundan derleyici uyarısıyla sonuçlanır.
  • third olabilirnull. Örneğin, , ancak System.String. Bu varyasyonlardan herhangi biri kabul edilebilir. Derleyici, önce null olmadığını denetlemeden başvuruyu third geri alırsanız sizi uyararak size yardımcı olur.

Önemli

Yukarıda gösterildiği gibi null atanabilir başvuru türleri özelliğini kullanmak için, null atanabilir bir bağlam içinde olmalıdır. Bu, sonraki bölümde ayrıntılı olarak anlatılır.

Boş değer atanabilir bağlam

Null atanabilir bağlamlar, derleyicinin başvuru türü değişkenlerini nasıl yorumlayabilmesi için ayrıntılı denetim sağlar. Dört olası null atanabilir bağlam vardır:

  • disable: Derleyici, C# 7.3 ve önceki sürümlere benzer şekilde davranır.
  • enable: Derleyici tüm null başvuru analizini ve tüm dil özelliklerini etkinleştirir.
  • warnings: Derleyici tüm null çözümlemelerini gerçekleştirir ve kodun başvuruyu nullkaldırabileceği durumlarda uyarı verir.
  • annotations: Derleyici, kodun başvuruyu kaldırabileceği nulldurumlarda null çözümleme gerçekleştirmez veya uyarı göndermez, ancak yine de null atanabilir başvuru türlerini ? ve null-forgiving işleçlerini (!) kullanarak kodunuz için açıklama ekleyebilirsiniz.

Bu modülün kapsamı ya da disableenable null atanabilir bağlamlar olarak belirlenmiştir. Daha fazla bilgi için Null atanabilir başvuru türlerine başvurun: Null atanabilir bağlamlar.

Boş değer atanabilir başvuru türlerini etkinleştirme

C# proje dosyası (.csproj) içinde, <Nullable> öğesine bir alt <Project> düğüm ekleyin (veya var olan <PropertyGroup> bir düğüme ekleyin). Bu, null atanabilir bağlamı enable projenin tamamına uygular.

<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
        <Nullable>enable</Nullable>
    </PropertyGroup>

    <!-- Omitted for brevity -->

</Project>

Alternatif olarak, derleyici yönergesini kullanarak null atanabilir bağlamı bir C# dosyasıyla sınırlayabilirsiniz.

#nullable enable

Yukarıdaki C# derleyici yönergesi işlevsel olarak proje yapılandırmasına eşdeğerdir, ancak kapsamı içinde bulunduğu dosyayla belirlenmiştir. Daha fazla bilgi için bkz Null başvuru türleri: Boş değer atanabilir bağlamlar (belgeler)

Önemli

.NET 6.0 ve üzeri ile başlayan tüm C# proje şablonlarında, .csproj dosyasında null atanabilir bağlam varsayılan olarak etkinleştirilir.

Boş değer atanabilir bağlam etkinleştirildiğinde yeni uyarılar alırsınız. Null değer atanabilir bir bağlamda analiz edildiğinde iki uyarı içeren önceki FooBar örneği göz önünde bulundurun:

  1. FooBar fooBar = null; satırının null atamasında bir uyarı var: C# Uyarısı CS8600: Null literal veya olası null değeri, atanamaz türde dönüştürülüyor.

    C# Uyarısı CS8600: Null değişmez değerini veya olası null değeri null atanamaz türe dönüştürme işleminin ekran görüntüsü.

  2. Satırda _ = fooBar.ToString(); da bir uyarı vardır. Derleyici bu kez fooBar null olabileceğinden endişe ediyor: C# Uyarısı CS8602: Muhtemelen null bir başvurunun dereferansı.

    C# Uyarısı CS8602: Olası null bir referansın çözülmesi.

Önemli

Tüm uyarılara tepki verirseniz ve bunları ortadan kaldırsanız bile garantili null güvenlik yoktur. Derleyicinin çözümlemesini geçirecek ancak çalışma zamanıyla NullReferenceExceptionsonuçlanacak bazı sınırlı senaryolar vardır.

Özet

Bu ünitede, C# dilinde boş değer atanabilir bir bağlamı etkinleştirerek karşı NullReferenceExceptionkorumaya yardımcı olduğunu öğrendiniz. Sonraki ünitede amacınızı boş değer atanabilir bir bağlamda açıkça ifade etme hakkında daha fazla bilgi edineceksiniz.