Safe
擴展方法永遠不會回傳 null,但編譯器似乎無法檢測到這一點。我想我讀過一些關于這是一個有意的字串設計決定,但不記得何時何地。任何人都可以解釋如何解決這個問題(即幫助編譯器)或解釋為什么它是故意這樣的嗎?
Foo? foo = null;
Bar bar = new();
// CS8601: Possible null reference assignment.
bar.NoNullsHere = foo?.Text().Safe();
// No error with the trailing exclamation point
bar.NoNullsHere = foo?.Text().Safe()!;
public static class StringExtensionMethods
{
public static string Safe(this string? obj) => obj is null ? string.Empty : obj!;
}
public class Foo
{
public string? Text() => "has a value, but could be null or empty";
}
public class Bar
{
public string NoNullsHere { get; set; } = string.Empty;
}
uj5u.com熱心網友回復:
您正在使用 null 傳播運算子。
bar.NoNullsHere = foo?.Text().Safe();
// consider it will work like below
if (foo != null)
{
bar.NoNullsHere = foo.Text().Safe();
}else
{
bar.NoNullsHere = null;
}
所以編譯器是對的bar.NoNullsHere
可以為null
uj5u.com熱心網友回復:
當然可以,Safe()
不能回傳null。但這不是你的問題。以下是您如何使用它:
foo?.Text().Safe();
如果foo
為空怎么辦?然后怎樣呢?該運算式的結果應該是什么?當然,它將為空,因為這就是?.
運算子的行為方式。這就是為什么您會收到該錯誤的原因。
您必須檢查它foo
是否為 null 才能按您的意愿作業。
或者,你真的不需要Safe()
,你可以這樣做:
bar.NoNullsHere = foo?.Text() ?? string.Empty;
它處理foo
null 和Text()
回傳 null,并將其合并為一個空字串。
uj5u.com熱心網友回復:
這種?.
讓一切都變得“正確聯想”(抱歉,我找不到更好的詞)。
foo?.Text().Safe();
意思是“Text().Safe()
如果foo
不為空則運行”。因此,如果foo
為null,它將不執行任何操作并評估為null
. 如果有幫助,請將其視為:
// not valid syntax, but IMO a good mental image
foo?.(Text().Safe());
這種行為也是為什么你只能?
在鏈中使用一個:
someNullableThing?.Property1.Property2.Property3
如果?.
是“左關聯”,someNullableThing?.Property1
則可以為空,并且您必須將?
所有位置放在鏈上,即使PropertyN
s 不可為空。請注意,某些語言(如 Kotlin)實際上是這樣實作的。
也就是說,我認為你的意思是:
bar.NoNullsHere = (foo?.Text()).Safe();
foo.Safe()
即使foo
為空,這也會運行。
uj5u.com熱心網友回復:
有趣的案例......這個問題被問到 dotnet 團隊:
警告將條件空運算子與接受空參考的擴展方法一起使用
可空參考型別特性的核心是不完美的,它更像是一種檢測空值的啟發式方法,而不是一種保證。這意味著我們的分析在某些情況下可能是錯誤的。期望代碼會遇到編譯器錯誤地將值推斷為 maybe-null 的情況,而實際上它肯定不是,反之亦然。因此,作為一般規則,當客戶進行對可空型別系統而言顯得多余的空檢查時,我們不會向客戶發出警告。
總之,分析器并不完美,無法處理這種情況。
要解決此問題(洗掉警告),您可以:
bar.NoNullsHere = foo?.Text().Safe()!
//or
bar.NoNullsHere = StringExtensionMethods.Safe(foo?.Text());
這是無用的額外作業……但它是分析器的限制。
幾個答案建議使用 null 傳播運算子。這是不準確的,因為這不會呼叫負責生成默認值的方法 Safe :
string? text = null;
string noNullsHere;
noNullsHere = text?.Safe() ?? "Default from Main";
Console.WriteLine(noNullsHere);
// Output : Default from Main
noNullsHere = StringExtensionMethods.Safe(text);
Console.WriteLine(noNullsHere);
// Ouput : Default from Safe
public static class StringExtensionMethods
{
public static string Safe(this string? obj) => obj is null ? "Default from Safe" : obj!;
}
public class Bar
{
public string NoNullsHere { get; set; } = string.Empty;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/536494.html
標籤:C#
上一篇:如何在bash腳本中執行帶有引數的“runuser”命令?
下一篇:c#函式中的排序串列