Amacı ifade etme
- 5 dakika
Önceki ünitede, C# derleyicisinin ile korunmaya NullReferenceExceptionyardımcı olmak için nasıl statik analiz gerçekleştirebileceğini öğrendiniz. Boş değer atanabilir bağlamı etkinleştirmeyi de öğrendinsiniz. Bu ünitede amacınızı null atanabilir bir bağlam içinde açıkça ifade etme hakkında daha fazla bilgi edineceksiniz.
Değişkenleri bildirme
Boş değer atanabilir bağlam etkinleştirildiğinde, derleyicinin kodunuzu nasıl göreceğine ilişkin daha fazla görünürlüğe sahip olursunuz. Null atanabilir etkinleştirilmiş bir bağlamdan oluşturulan uyarılara göre işlem yapabilirsiniz ve bunu yaparken amaçlarınızı açıkça tanımlarsınız. Örneğin, kodu incelemeye FooBar devam edelim ve bildirimi ve atamayı inceleyelim:
// Define as nullable
FooBar? fooBar = null;
öğesine ? eklenene FooBardikkat edin. Bu, derleyiciye açıkça null atanabilir olmasını istediğinizi fooBar bildirir. Null atanabilir olmasını amaçlamıyorsanız fooBar ancak yine de uyarıdan kaçınmak istiyorsanız aşağıdakileri göz önünde bulundurun:
// Define as non-nullable, but tell compiler to ignore warning
// Same as FooBar fooBar = default!;
FooBar fooBar = null!;
Bu örnek, derleyiciye !bu değişkeni açıkça null olarak başlatmanızı belirten null-forgiving (null) işlecini ekler. Derleyici bu başvurunun null olduğu konusunda uyarı vermez.
Mümkünse null değer atanamayan değişkenlerinizi bildirildiğinde değer olmayannull değerler atamak iyi bir yöntemdir:
// Define as non-nullable, assign using 'new' keyword
FooBar fooBar = new(Id: 1, Name: "Foo");
İşleçler
Önceki ünitede açıklandığı gibi, C# amacınızı null atanabilir başvuru türleri etrafında ifade etmek için birkaç işleç tanımlar.
Null-forgiving (!) işleci
Önceki bölümde null-forgiving işleciyle (!) tanıştırıldınız. Derleyiciye CS8600 uyarısını yoksaymalarını söyler. Bu, derleyiciye ne yaptığınızı bildiğinizi söylemenin bir yoludur, ancak aslında ne yaptığınızı bilmeniz gerektiği uyarısıyla birlikte gelir!
Null atanabilir bir bağlam etkinleştirildiğinde null atanamaz türleri başlatırken derleyiciden açıkça af istemeniz gerekebilir. Örneğin, aşağıdaki kodu göz önünde bulundurun:
#nullable enable
using System.Collections.Generic;
var fooList = new List<FooBar>
{
new(Id: 1, Name: "Foo"),
new(Id: 2, Name: "Bar")
};
FooBar fooBar = fooList.Find(f => f.Name == "Bar");
// The FooBar type definition for example.
record FooBar(int Id, string Name);
Yukarıdaki örnekte, FooBar fooBar = fooList.Find(f => f.Name == "Bar"); döndürebileceğinden Findbir CS8600 uyarısı null oluşturur. Bu, bu null bağlamda null atanamaz olan öğesine atanabilir fooBar. Ancak, bu eşleştirilmiş örnekte, bunun Find hiçbir zaman yazılı olarak döndürülmeyeceğini null biliyoruz. Bu amacı null-forgiving işleciyle derleyiciye ifade edebilirsiniz:
FooBar fooBar = fooList.Find(f => f.Name == "Bar")!;
öğesinin ! sonundaki öğesini fooList.Find(f => f.Name == "Bar")not edin. Bu, derleyiciye yöntemi tarafından döndürülen nesnenin olabileceğini Findbildiğinizi null ve sorun olmadığını bildirir.
Null-forgiving işlecini, yöntem çağrısı veya özellik değerlendirmesi öncesinde satır içi nesneye de uygulayabilirsiniz. Başka bir eşleştirilmiş örneği düşünün:
List<FooBar>? fooList = FooListFactory.GetFooList();
// Declare variable and assign it as null.
FooBar fooBar = fooList.Find(f => f.Name == "Bar")!; // generates warning
static class FooListFactory
{
public static List<FooBar>? GetFooList() =>
new List<FooBar>
{
new(Id: 1, Name: "Foo"),
new(Id: 2, Name: "Bar")
};
}
// The FooBar type definition for example.
record FooBar(int Id, string Name);
Yukarıdaki örnekte:
-
GetFooList, null atanabilir bir türList<FooBar>?döndüren statik bir yöntemdir. -
fooListtarafından döndürülenGetFooListdeğer atanır. - atanan değer
fooList.Find(f => f.Name == "Bar");olabileceğindenfooListderleyici üzerindenullbir uyarı oluşturur. -
fooList'ninnullolmadığını varsayarsak,Finddöndürebilirnull, ancak döndürmeyeceğini biliyoruz, dolayısıyla null-forgiving işleci uygulanır.
Uyarıyı devre dışı bırakmak için null-forgiving işlecini fooList uygulayabilirsiniz:
FooBar fooBar = fooList!.Find(f => f.Name == "Bar")!;
Not
Null-forgiving işlecini dikkatle kullanmanız gerekir. Yalnızca bir uyarıyı kapatmak için bunu kullanmak, derleyiciye olası null uyuşmazlıkları keşfetmenize yardımcı olmamasını söylemiş olduğunuz anlamına gelir. Bunu tedbirli ve yalnızca emin olduğunuzda kullanın.
Daha fazla bilgi için ! (null-forgiving) işleci (C# başvurusu).
Null birleşim (??) işleci
Null atanabilir türlerle çalışırken, bunların şu anda null olup olmadığını değerlendirmeniz ve belirli eylemleri gerçekleştirmeniz gerekebilir. Örneğin, null atanabilir bir tür atandığında null veya bunlar başlatılmadığında, onlara null olmayan bir değer atamanız gerekebilir. Burada null birleşim işleci (??) yararlıdır.
Aşağıdaki örneği inceleyin:
public void CalculateSalesTax(IStateSalesTax? salesTax = null)
{
salesTax ??= DefaultStateSalesTax.Value;
// Safely use salesTax object.
}
Yukarıdaki C# kodunda:
-
salesTaxparametresi null atanabilirIStateSalesTaxolarak tanımlanır. - yöntem gövdesinde,
salesTaxnull birleşim işleci kullanılarak koşullu olarak atanır.- Bu, geçirildiyse
salesTaxdeğerininnullolmasını sağlar.
- Bu, geçirildiyse
İpucu
Bu işlev olarak aşağıdaki C# koduna eşdeğerdir:
public void CalculateSalesTax(IStateSalesTax? salesTax = null)
{
if (salesTax is null)
{
salesTax = DefaultStateSalesTax.Value;
}
// Safely use salesTax object.
}
Aşağıda null birleşim işlecinin yararlı olabileceği başka bir yaygın C# deyimi örneği verilmiştir:
public sealed class Wrapper<T> where T : new()
{
private T _source;
// If given a source, wrap it. Otherwise, wrap a new source:
public Wrapper(T source = null) => _source = source ?? new T();
}
Yukarıdaki C# kodu:
- Genel tür parametresinin ile kısıtlandığı genel sarmalayıcı sınıfını
new()tanımlar. - Oluşturucu, varsayılan olarak olarak kabul edilen bir
T sourceparametreyinullkabul eder. - Sarmalanan
_sourcekoşullu olarak birnew T()olarak başlatılır.
Daha fazla bilgi için ?? ve ??= işleçleri (C# başvurusu).
Null koşullu (?.) işleci
Null atanabilir türlerle çalışırken, bir null nesnenin durumuna göre koşullu olarak eylemler gerçekleştirmeniz gerekebilir. Örneğin: önceki ünitede FooBar kayıt, başvurusu NullReferenceExceptionkaldırılarak göstermek null için kullanılmıştır. Bu, çağrıldığında ToString ortaya çıkan bir durumdu. Aynı örneği göz önünde bulundurun, ancak şimdi null-koşullu işlecini uygulayın:
using System;
// Declare variable and assign it as null.
FooBar fooBar = null;
// Conditionally dereference variable.
var str = fooBar?.ToString();
Console.Write(str);
// The FooBar type definition.
record FooBar(int Id, string Name);
Yukarıdaki C# kodu:
- Koşullu başvurular
fooBar, öğesinin sonucunuToStringdeğişkenestratar.-
strDeğişken türündedirstring?(null atanabilir dize).
-
- değerini
strhiçbir şey olmayan standart çıkışa yazar. - Arama
Console.Write(null)geçerli olduğundan uyarı yok. - Aramanız
Console.Write(str.Length)gerekirse bir uyarı alırsınız çünkü null başvuruyu kaldırmış olabilirsiniz.
İpucu
Bu işlev olarak aşağıdaki C# koduna eşdeğerdir:
using System;
// Declare variable and assign it as null.
FooBar fooBar = null;
// Conditionally dereference variable.
string str = (fooBar is not null) ? fooBar.ToString() : default;
Console.Write(str);
// The FooBar type definition.
record FooBar(int Id, string Name);
Amacınızı daha fazla ifade etmek için işleci birleştirebilirsiniz. Örneğin, ve ?. işleçlerini zincirleyebilirsiniz??:
FooBar fooBar = null;
var str = fooBar?.ToString() ?? "unknown";
Console.Write(str); // output: unknown
Daha fazla bilgi için ?. ve ?[] (null-koşullu) işleçlerine başvurun.
Özet
Bu ünitede, null atanabilirlik amacınızı kodda ifade etme hakkında bilgi edinmişsinizdir. Sonraki ünitede öğrendiklerini var olan bir projeye uygulayacaksınız.