Burada neler olduğuna dair makul bir tahmin yapabilirim , ama hepsi biraz karmaşık :) Taslak şartnamede açıklanan null durumu ve null izlemeyi içerir . Temel olarak, geri dönmek istediğimiz noktada, derleyici ifadenin durumu "null değil" yerine "belki null" olduğunda uyarır.
Bu cevap sadece "sonuçlar burada" değil, biraz anlatı biçiminde ... Umarım bu şekilde daha faydalıdır.
Alanlardan kurtularak örneği biraz basitleştireceğim ve bu iki imzadan biriyle bir yöntem düşüneceğim:
public static string M(string? text)
public static string M(string text)
Aşağıdaki uygulamalarda, her yönteme farklı bir sayı verdim, böylece belirli örneklere açık bir şekilde başvurabilirim. Aynı zamanda tüm uygulamaların aynı programda bulunmasına izin verir.
Aşağıda açıklanan vakaların her birinde, çeşitli şeyler yapacağız, ancak geri dönmeye çalışacağız text
- bu text
önemli.
Koşulsuz iade
İlk olarak, doğrudan iade etmeye çalışalım:
public static string M1(string? text) => text; // Warning
public static string M2(string text) => text; // No warning
Şimdiye kadar, çok basit. Yöntemin başlangıcında parametrenin null değeri, tür ise "belki null" ve tür string?
ise "null" olur string
.
Basit koşullu getiri
Şimdi if
ifade koşulunun içinde null olup olmadığını kontrol edelim . (Aynı etkiye sahip olacağına inandığım koşullu operatörü kullanardım, ancak soruya daha doğru kalmak istedim.)
public static string M3(string? text)
{
if (text is null)
{
return "";
}
else
{
return text; // No warning
}
}
public static string M4(string text)
{
if (text is null)
{
return "";
}
else
{
return text; // No warning
}
}
Harika, bu yüzden if
durumun kendisinin geçersizliği kontrol ettiği bir ifade içinde, ifadenin her bir dalındaki değişkenin durumu if
farklı olabilir: else
blok içinde , durum her iki kod parçasında da "boş" değildir. Bu yüzden özellikle M3'te durum "belki null" değerinden "null değil" e değişir.
Yerel değişkenle koşullu getiri
Şimdi bu koşulu yerel bir değişkene kaldırmaya çalışalım:
public static string M5(string? text)
{
bool isNull = text is null;
if (isNull)
{
return "";
}
else
{
return text; // Warning
}
}
public static string M6(string text)
{
bool isNull = text is null;
if (isNull)
{
return "";
}
else
{
return text; // Warning
}
}
Hem M5 hem de M6 uyarı verir. Yani sadece M5'te (M3'te yaptığımız gibi) devlet değişikliğinin “belki null” dan “null değil” e pozitif etkisini elde etmekle kalmıyoruz ... M6'da durumun geçtiği yerdeki karşıt etkiyi elde ediyoruz ” null değil, "belki null". Bu beni gerçekten şaşırttı.
Görünüşe göre şunu öğrendik:
- Durum bilgisini yaymak için "yerel değişkenin nasıl hesaplandığı" mantığı kullanılmaz. Daha sonra.
- Boş bir karşılaştırma yapmak derleyiciyi daha önce boş olmadığını düşündüğü bir şeyin sonuçta boş olabileceği konusunda uyarabilir.
Yok sayılan bir karşılaştırmadan sonra koşulsuz getiri
Koşulsuz bir dönüşten önce bir karşılaştırma yaparak bu mermi noktalarının ikincisine bakalım. (Yani karşılaştırmanın sonucunu tamamen görmezden geliyoruz.):
public static string M7(string? text)
{
bool ignored = text is null;
return text; // Warning
}
public static string M8(string text)
{
bool ignored = text is null;
return text; // Warning
}
M8'in M2'ye eşdeğer olması gerektiğini nasıl hissettiğine dikkat edin - her ikisinin de koşulsuz olarak döndükleri bir null olmayan parametresi vardır - ancak null ile karşılaştırmanın başlatılması durumu "null" değerinden "belki null" değerine değiştirir. Durumdan text
önce vazgeçmeye çalışarak bunun hakkında daha fazla kanıt elde edebiliriz :
public static string M9(string text)
{
int length1 = text.Length; // No warning
bool ignored = text is null;
int length2 = text.Length; // Warning
return text; // No warning
}
İfadenin return
şu anda nasıl bir uyarısı olmadığına dikkat edin: Yürütmeden sonrakitext.Length
durum "boş değil" (çünkü bu ifadeyi başarıyla yürütürsek boş olamaz). Bu nedenle text
parametre, türü nedeniyle "null değil" olarak başlar, null karşılaştırması nedeniyle "belki null" olur, sonra tekrar "null" olmaz text2.Length
.
Hangi karşılaştırmalar devleti etkiler?
Yani bu bir karşılaştırma text is null
... benzer karşılaştırmaların ne etkisi var? Aşağıda, tümü boş değerli bir dize parametresiyle başlayan dört yöntem daha vardır:
public static string M10(string text)
{
bool ignored = text == null;
return text; // Warning
}
public static string M11(string text)
{
bool ignored = text is object;
return text; // No warning
}
public static string M12(string text)
{
bool ignored = text is { };
return text; // No warning
}
public static string M13(string text)
{
bool ignored = text != null;
return text; // Warning
}
Yani rağmen x is object
şu ana önerilen bir alternatiftir x != null
aynı etkisi yoktur,: Sadece bir karşılaştırma null (herhangi biriyle is
, ==
ya !=
) "belki boş" ile "değil boş" dan durumunu değiştirir.
Durumun kaldırılmasının neden bir etkisi var?
Daha önce ilk kurşun noktamıza geri dönersek, neden M5 ve M6 yerel değişkene yol açan durumu dikkate almıyor? Bu beni başkalarını şaşırtacak kadar şaşırtmıyor. Derleyiciye ve belirtime bu tür bir mantık oluşturmak çok fazla iştir ve nispeten az yarar sağlar. İşte bir şeyin satır içi yapmanın bir etkisi olduğu nullabilite ile ilgisi olmayan başka bir örnek:
public static int X1()
{
if (true)
{
return 1;
}
}
public static int X2()
{
bool alwaysTrue = true;
if (alwaysTrue)
{
return 1;
}
// Error: not all code paths return a value
}
Olsa biz biliyoruz alwaysTrue
her zaman doğru olacaktır, bu sonra kod yapmak şartnamede gereksinimlerini tatmin etmiyor if
ihtiyacımız olan şey ulaşılamaz açıklamada,.
İşte kesin atamanın etrafında başka bir örnek:
public static void X3()
{
string x;
bool condition = DateTime.UtcNow.Year == 2020;
if (condition)
{
x = "It's 2020.";
}
if (!condition)
{
x = "It's not 2020.";
}
// Error: x is not definitely assigned
Console.WriteLine(x);
}
Olsa biz kod olanların tam olarak bir gireceğini biliyorum if
deyimi organları, işe spec dikkat hiçbir şey yok. Statik analiz araçları bunu yapabilir, ancak dil spesifikasyonuna koymaya çalışmak kötü bir fikir olacaktır, IMO - statik analiz araçlarının zaman içinde gelişebilen, ancak çok fazla olmayan her türlü buluşsal yöntemlere sahip olması iyidir. bir dil belirtimi için.