詳解C#中檢查null的語(yǔ)法糖
今天看到已經(jīng)更新了devblogs,新增的C# 11的!!(用于檢查null的語(yǔ)法)經(jīng)過非常長(zhǎng)的討論,最后取消了。然后我又想起來null檢查,這個(gè)可以說一說。
函數(shù)參數(shù)null檢查
傳統(tǒng)寫法
寫一個(gè)函數(shù)的時(shí)候,最經(jīng)典的檢查,估計(jì)也是大家最常使用的null檢查,應(yīng)該是這樣的吧:
public static void GetV1(string prompt) { if (prompt is null) throw new ArgumentNullException(nameof(prompt)); Console.WriteLine(prompt); }
ThrowIfNull
這個(gè)寫起來也沒啥問題,但是總覺得有點(diǎn)不舒適。.NET 6在ArgumentNullException
中新增了ThrowIfNull
方法,可以寫的更優(yōu)雅一點(diǎn)。
public static void GetV2(string prompt) { ArgumentNullException.ThrowIfNull(prompt); Console.WriteLine(prompt); }
異常的時(shí)候,就會(huì)出現(xiàn):System.ArgumentNullException: 'Value cannot be null. (Parameter 'prompt')'
。這個(gè)是不是簡(jiǎn)單了點(diǎn)?可是還是需要寫一行。
C# 11的!!語(yǔ)法(已經(jīng)取消)
C# 11剛preview的時(shí)候,我就瞄到了這個(gè)特性,現(xiàn)在依然可以通過設(shè)置preview來進(jìn)行啟用,但是以后正式發(fā)布估計(jì)就不行了。
它通過在參數(shù)后面疊加!!表示此參數(shù)不可為空,運(yùn)行時(shí)會(huì)自動(dòng)進(jìn)行檢查,如果是null就直接彈出錯(cuò)誤。
public static void GetV3(string prompt!!) { Console.WriteLine(prompt); }
這個(gè)代碼會(huì)被編譯器翻譯成:
public static void GetV3(string prompt!!) { if (prompt is null) { throw new ArgumentNullException(nameof(prompt)); } Console.WriteLine(prompt); }
這樣大家就可以專注于業(yè)務(wù)代碼,不需要經(jīng)??紤]異常檢查了。至于為什么這個(gè)東西最后還是被刪除了,可以從討論中看到一絲端倪,首先是感覺非常糾結(jié)于這個(gè)語(yǔ)法,兩個(gè)嘆號(hào);然后就是已經(jīng)有比較多的方式可以實(shí)現(xiàn)檢查了,這個(gè)東西是否有必要。反正最終是以后再討論了,不過也可以看出來C#語(yǔ)言工作組對(duì)語(yǔ)言的特性討論非常謹(jǐn)慎。
他們還討論了很多別的形式,每種都提出了各自的優(yōu)缺點(diǎn)挺有意思的,能看出來有一點(diǎn)設(shè)計(jì)語(yǔ)言的嚴(yán)謹(jǐn)和小強(qiáng)迫癥在,點(diǎn)贊~
void M(string s!!); void M(string! s); void M(string s!); void M(notnull string s); void M(string s ?? throw); void M(string s is not null); void M(checked string s); void M(string s) where s is not null;
有關(guān)null的一些操作
說起這個(gè),就順便說說c#處理null的另外幾個(gè)語(yǔ)法糖吧。
??
如果左邊是的null,那么返回右邊的操作數(shù),否則就返回左邊的操作數(shù),這個(gè)在給變量賦予默認(rèn)值非常好用。
int? a = null; int b = a ?? -1; Console.WriteLine(b); // output: -1
??=
當(dāng)左邊是null,那么就對(duì)左邊的變量賦值成右邊的
int? a = null; a ??= -1; Console.WriteLine(a); // output: -1
?.
當(dāng)左邊是null,那么不執(zhí)行后面的操作,直接返回空,否則就返回實(shí)際操作的值。
using System; public class C { public static void Main() { string i = null; int? length = i?.Length; Console.WriteLine(length ?? -1); //output: -1 } }
?[]
索引器操作,和上面的操作類似
using System; public class C { public static void Main() { string[] i = null; string result = i?[1]; Console.WriteLine(result ?? "null"); // output:null } }
注意,如果鏈?zhǔn)绞褂玫倪^程中,只要前面運(yùn)算中有一個(gè)是null,那么將直接返回null結(jié)果,不會(huì)繼續(xù)計(jì)算。下面兩個(gè)操作會(huì)有不同的結(jié)果。
using System; public class C { public static void Main() { string[] i = null; Console.WriteLine(i?[1]?.Substring(0).Length); //不彈錯(cuò)誤 Console.WriteLine((i?[1]?.Substring(0)).Length) // System.NullReferenceException: Object reference not set to an instance of an object. } }
一些操作
//參數(shù)給予默認(rèn)值 if(x == null) x = "str"; //替換 x ??= "str"; //條件判斷 string x; if(i<3) x = y; else { if(z != null) x = z; else z = "notnull"; } //替換 var x = i < 3 ? y : z ?? "notnull" //防止對(duì)象為null的時(shí)候,依然執(zhí)行代碼 if(obj != null) obj.Act(); //替換 obj?.Act(); //Dictionary取值與賦值 string result; if(dict.ContainKey(key)) { if(dict[key] == null) result = "有結(jié)果為null"; else result = dict[key]; } else result = "無結(jié)果為null"; //替換 var result= dict.TryGetValue(key, out var value) ? value ?? "有結(jié)果為null" : "無結(jié)果為null";
結(jié)語(yǔ)
原來新定的C# 11提供了一個(gè)新的??,話說我個(gè)人還是挺喜歡這個(gè)特性的,不管以什么形式出現(xiàn)吧,期待以后再見。
C#中為了處理null給我們準(zhǔn)備了許多的語(yǔ)法糖,只能說非常簡(jiǎn)便了。有很多人會(huì)說這個(gè)可讀性不好,或者覺得這是“茴字的幾種寫法”似的歪門邪道,我只能說,傳統(tǒng)的語(yǔ)法也不是說取消了,語(yǔ)言有發(fā)展,只要還是比較審慎的,我覺得還是一件好事。
到此這篇關(guān)于詳解C#中檢查null的語(yǔ)法糖的文章就介紹到這了,更多相關(guān)C#檢查null內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
WinForm實(shí)現(xiàn)窗體最大化并遮蓋任務(wù)欄的方法
這篇文章主要介紹了WinForm實(shí)現(xiàn)窗體最大化并遮蓋任務(wù)欄的方法,涉及C#實(shí)現(xiàn)WinForm窗體全屏顯示的實(shí)現(xiàn)及調(diào)用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08c#遍歷System.drawing.Color下面的所有顏色以及名稱以查看
c#遍歷System.drawing.Color下面的所有顏色以及名稱以查看,需要的朋友可以參考一下2013-02-02使用C#調(diào)用百度地圖并實(shí)現(xiàn)坐標(biāo)點(diǎn)的設(shè)置以及讀取示例
這篇文章主要介紹了使用C#調(diào)用百度地圖并實(shí)現(xiàn)坐標(biāo)點(diǎn)的設(shè)置以及讀取示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07C#實(shí)現(xiàn)變量交換、斐波那契數(shù)列、質(zhì)數(shù)、回文方法合集
這篇文章介紹了C#實(shí)現(xiàn)變量交換、斐波那契數(shù)列、質(zhì)數(shù)、回文的方法合集,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02C#數(shù)據(jù)結(jié)構(gòu)與算法揭秘四 雙向鏈表
上節(jié)說過這節(jié)會(huì)講雙向鏈表,環(huán)形鏈表和應(yīng)用舉例,我們開始吧?。。?!2012-11-11詳解C#如何實(shí)現(xiàn)隱式類型轉(zhuǎn)換
Result?類型是許多編程語(yǔ)言中處理錯(cuò)誤的常用方式,包括?C#?的?dotNext?庫(kù)。在本文中,我們將通過例子回顧?C#?中?using?語(yǔ)句和隱式類型轉(zhuǎn)換的使用,感興趣的可以了解一下2023-01-01C#語(yǔ)法糖(Csharp Syntactic sugar)大匯總
首先需要聲明的是“語(yǔ)法糖”這個(gè)詞絕非貶義詞,它可以給我?guī)矸奖?,是一種便捷的寫法,編譯器會(huì)幫我們做轉(zhuǎn)換;而且可以提高開發(fā)編碼的效率,在性能上也不會(huì)帶來?yè)p失。這讓java開發(fā)人員羨慕不已,呵呵。2010-06-06C#實(shí)現(xiàn)套接字發(fā)送接收數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)套接字發(fā)送接收數(shù)據(jù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Unity通過腳本創(chuàng)建網(wǎng)格Mesh的方法
Unity中的網(wǎng)格作為組件不能脫離物體單獨(dú)存在,通過新建腳本來實(shí)現(xiàn)相關(guān)操作,本文重點(diǎn)給大家介紹Unity通過腳本創(chuàng)建網(wǎng)格Mesh的方法,感興趣的朋友一起看看吧2022-04-04解析使用enumerator模式簡(jiǎn)化異步操作的詳解
本篇文章是對(duì)使用enumerator模式簡(jiǎn)化異步操作進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05