最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

C# 邏輯與括號(hào)模式

2023-01-16 10:34 作者:SunnieShine  | 我要投稿

因?yàn)槟J狡ヅ淅锏拿總€(gè)模式并不是一個(gè)“數(shù)據(jù)信息”,因此我們無(wú)法直接對(duì)模式用 &&|| 等符號(hào)來(lái)進(jìn)行拼接組合。C# 為了解決這個(gè)問(wèn)題,多了三個(gè)關(guān)鍵字:and、ornot 來(lái)拼接模式。

1、合取模式

合取模式用 and 拼接模式,來(lái)表達(dá)這些模式都必須成立。

比如這里,>= 'a' and <= 'z' 整個(gè)表達(dá)式用來(lái)表達(dá),>= 'a'<= 'z' 兩個(gè)條件必須都滿足。如果要寫分開(kāi),就必須寫成 c is >= 'a' && c is <= 'z'。

2、析取模式

析取模式用 or 拼接。

注意,or 拼接了前面 >= 'a' and <= 'z' 和后面 >= 'A' and <= 'Z' 兩個(gè)模式。or 表示兩個(gè)模式有一個(gè)模式能夠匹配成功就可以。

這里我們介紹了一種新的語(yǔ)法:C# 允許模式匹配的內(nèi)部使用小括號(hào),來(lái)斷開(kāi)和分隔一個(gè)模式。andor 的模式名稱不變,但這個(gè)小括號(hào)套起來(lái)的模式,C# 稱之為括號(hào)模式。

3、取反模式

取反模式用 not。

最常見(jiàn)的就是這里。我們?nèi)绻袛鄬?duì)象是不是不為 null,那么我們最常用的就是寫成 is not null。is null 屬于前面的常量模式,判斷對(duì)象是不是 null。它和 == 運(yùn)算符的區(qū)別是,== 運(yùn)算符可重載,重載會(huì)影響 == 的判斷和使用邏輯;而 is 是永遠(yuǎn)不變的判斷模式。

4、混用三種模式

當(dāng)然,你也可以混用到 andor 關(guān)鍵字拼接起來(lái)的模式里。

這表示 ch 是不是字符 0 到 9,或者是小數(shù)點(diǎn)。將其取反:

這就表示取反。當(dāng)然了,你可以使用類似數(shù)學(xué)知識(shí),將 not 套到小括號(hào)里:

這 4 行內(nèi)容可以幫助你理解和拼接模式的具體內(nèi)容。

5、三種模式的優(yōu)先級(jí)和結(jié)合性

稍微注意一下。合取式 and 和數(shù)學(xué)上是一樣的,比 or 更優(yōu)先推理,因此無(wú)需對(duì) andor 模式一起的復(fù)雜模式匹配添加括號(hào):

比如這樣,(>= 'a' and <= 'z')(>= 'A' and <= 'Z') 的小括號(hào)可以不要。

取反式的話,因?yàn)樗缓鸵粋€(gè)模式結(jié)合使用,不像是 andor 需要兩個(gè)模式結(jié)合,因此 not 的優(yōu)先級(jí)比 andnot 都要高。所以,上面的例子里,這個(gè)寫法你應(yīng)該是知道哪些地方省略了小括號(hào)。

6、對(duì)括號(hào)模式和對(duì)位模式下小括號(hào)的辨識(shí)

不知道你注意到了沒(méi)有。由于我們這里介紹了三種邏輯模式的類型,因此我們也不得不會(huì)產(chǎn)生和使用一種新的模式來(lái)自定義模式的結(jié)合??墒牵±ㄌ?hào)在模式匹配里本身就有別的用途:它表示一個(gè)對(duì)位模式。

那么,如果我們出現(xiàn)了像是使用對(duì)位模式的語(yǔ)法,但它又可以被當(dāng)成帶括號(hào)的模式的話,這不就出現(xiàn)二義性了嗎?

假設(shè)我們這里的 val 是一個(gè)對(duì)象。這里的模式 (3) 到底是什么呢?是括號(hào)模式里套了常量模式嗎?還是說(shuō),它是一個(gè)一元組解構(gòu)之后的對(duì)位模式呢?這我們無(wú)法確定,尤其是這個(gè) val 剛好可以解構(gòu)成這個(gè)樣子的時(shí)候。

所以,考慮到語(yǔ)法的嚴(yán)謹(jǐn)性和兼容性,小括號(hào)一直以來(lái)都是被視為“冗余后可去掉”的存在,因此,(3) 模式會(huì)被認(rèn)為是一個(gè)括號(hào)模式。而此時(shí)的 (3) 是一個(gè)很普通的常量模式,因此編譯器會(huì)提示你可以直接去掉這個(gè)小括號(hào)。

不信你可以打開(kāi) Visual Studio 試一試。如果你在寫一個(gè)對(duì)位模式匹配的時(shí)候,如果你寫了一段代碼:

當(dāng)此時(shí)光標(biāo)在 case ()() 之間時(shí),你肯定會(huì)往里面輸入模式:先判斷對(duì)象 a,然后逗號(hào),然后判斷對(duì)象 b??墒牵阕屑?xì)看看,如果你在輸入任何一個(gè)字符的時(shí)候,Intellisense 實(shí)際上并不是在給你提供 a 對(duì)象的屬性成員讓你對(duì)位匹配,而是比如 a: 啊、b: 啊之類的玩意兒。這是因?yàn)?,編譯器認(rèn)為你這里的小括號(hào)是括號(hào)模式,因此括號(hào)可以不要。于是,它視為你正在對(duì) (a, b) 這個(gè)元組類型 ValueTuple<T1, T2> 在做模式匹配。因此,它會(huì)提示給你看的是 a 字段和 b 字段(這兩個(gè)字段就是 ValueTuple<,> 類型下自帶的 Item1 屬性和 Item2 屬性在編譯期間的臨時(shí)引用名稱。所以,Intellisense 給出的比如 a: 的玩意兒,實(shí)際上是讓你填充進(jìn)去 a: 的字段名,用于屬性模式等模式的判斷。

這就解釋了前文“解構(gòu)模式”里的一節(jié)內(nèi)容:解構(gòu)和對(duì)位模式不要求判斷元素?cái)?shù)量至少兩個(gè),以及單元素的解構(gòu)模式要手動(dòng)消除二義性,這兩點(diǎn)的真實(shí)原因。

7、字面量在 and 模式下的類型可調(diào)整性

之所以放在這里說(shuō),是因?yàn)樽置媪渴强梢赃M(jìn)行類型匹配的,這也就是前文提到的常量模式。不過(guò),字面量有時(shí)候表現(xiàn)得并不一定非得是字面量本身的數(shù)據(jù)類型。

舉個(gè)例子,1 是 int 類型的字面量,但我們可以使用 and 連接常量模式和類型模式,使得這個(gè) 1 的類型發(fā)生變化:

請(qǐng)注意這里的 uint and 1 模式。uint 是表示類型必須是 uint 類型,而 1 卻又是 int 類型的字面量,這不會(huì)沖突嗎?答案是并不會(huì),字面量在模式匹配里會(huì)按照 and 里聯(lián)立給出的類型進(jìn)行隱式轉(zhuǎn)換。如果能夠轉(zhuǎn)換過(guò)去,那么就是允許的。

舉個(gè)例子,o is decimal and 1o is decimal and 1M 是一個(gè)意思,這個(gè)字面量 1 可以寫成 1M 但也可以直接寫成 1,因?yàn)樽置媪繒?huì)按照類型匹配的關(guān)系自動(dòng)轉(zhuǎn)換其表達(dá)的類型。不過(guò),這僅限于上下文可以暗示類型的情況。如果前面用的是 or 的話,就不行了。

8、is not var 組合模式到底是否為永假式?

所謂的永真和永假式,就是說(shuō)這個(gè)式子的判斷結(jié)果永遠(yuǎn)都是 truefalse。比如 if (true) 條件我們直接寫的是 true 字面量,這就是一種典型的永真式;當(dāng)然你不嫌復(fù)雜也可以寫 if (!false && true || false || true) 這種超級(jí)復(fù)雜的寫法。

那么,expr is var variable 的話,假設(shè) expr 是一個(gè)表達(dá)式的話,那么它是否是永真式呢?

這個(gè)問(wèn)題問(wèn)得好。expr is var variable 的模式匹配規(guī)則允許我們將表達(dá)式的結(jié)果在內(nèi)聯(lián)為布爾運(yùn)算邏輯的其中當(dāng)成一個(gè)永真的表達(dá)式在使用,目的是為了合并多個(gè)布爾表達(dá)式,使之直接稱為一個(gè)表達(dá)式還能跑起來(lái),這樣就可以不用使用一大堆的 if 判斷語(yǔ)句來(lái)影響可讀性和代碼量了。

不過(guò),is var 真的是永真的嗎?如果是的話,那么 is not var 不就是永假式么?永假的邏輯在 if 里還不如就寫成 if (false) 么?那這種東西還有何意義呢?

實(shí)際上,并非如此。is var 也不一定隨時(shí)都永真。考慮一種情況:解構(gòu)模式。解構(gòu)模式需要我們按照一定的情況對(duì)一個(gè)對(duì)象進(jìn)行解構(gòu)。它需要對(duì)象有一個(gè)解構(gòu)函數(shù),或者是包含一個(gè)可訪問(wèn)到的擴(kuò)展解構(gòu)函數(shù)。

考慮一種情況,假設(shè)這個(gè)對(duì)象是引用類型呢?那么解構(gòu)會(huì)隨時(shí)都成功嗎?不見(jiàn)得,對(duì)吧,因?yàn)樗约嚎赡苁?null。因此,在引用類型使用該模式組合的時(shí)候是有別的含義的,比如:

對(duì)于這種情況下,nullableExpression 在判斷的意思就是,如果它不可解構(gòu)為后面的三個(gè)變量的時(shí)候,則退出方法。在這個(gè)時(shí)候,“不可解構(gòu)”就對(duì)應(yīng)了它為 null 的時(shí)候。

不過(guò),對(duì)于純定義變量的 is var 的話,它肯定是直接賦值過(guò)去的,它根本不判空。因此,is not var 不可用于這種情況:因?yàn)樗兰?,?dǎo)致的情況就是無(wú)法完成匹配,因此 var 后面的變量你寫啥都沒(méi)有用:反正也不會(huì)成功賦值過(guò)去。因此后續(xù)的變量自然就不可能用得上它,因此編譯器也不允許你這么寫代碼。

9、聲明和 var 模式不能寫進(jìn) or 模式的兩側(cè)

這里就需要稍微提及一下注意事項(xiàng)了。實(shí)際上,雖然模式匹配很好用,但有些時(shí)候我們難免會(huì)因?yàn)橐恍┧季S不嚴(yán)謹(jǐn)導(dǎo)致錯(cuò)誤使用——本來(lái)我們覺(jué)得可以用,但實(shí)際上編譯器不認(rèn)為你這么寫是嚴(yán)謹(jǐn)?shù)?,于是不允許你這么用。你還納悶,為什么呢。

舉個(gè)例子。倘若我們要定義一個(gè)變量,并且判斷數(shù)值是否不為 0,那么我們可以這么做:

我們學(xué)了模式匹配后,就可以簡(jiǎn)化一下:

于是,我們使用 var val and not 0 來(lái)判斷了數(shù)值結(jié)果。這是合理的。

但是,我們總有時(shí)候,會(huì)因?yàn)榇a的書寫邏輯冗長(zhǎng)而不得不使用過(guò)濾思想:倒裝判斷邏輯,減少縮進(jìn),將所有的不滿足條件的情況直接給 returncontinue 提前退出,這樣可以減少縮進(jìn)。于是,我們就需要對(duì)上述表達(dá)式進(jìn)行取反:

可是,這樣的判斷顯然是有點(diǎn)丑的,因?yàn)槲覀冎苯訉?duì)模式取反還打了括號(hào)。我們嘗試將括號(hào)解開(kāi),將取反適用于內(nèi)部的模式。

按照基本的取反規(guī)則,and 要轉(zhuǎn)為 ornot 會(huì)變?yōu)?not not,也就是雙重否定,即可以直接去掉;反之沒(méi)有 not 的地方補(bǔ)一個(gè) not 即可:

似乎可以這么寫。但是,這樣的轉(zhuǎn)換真的合理嗎?實(shí)際上是否定的。我們來(lái)詳細(xì)說(shuō)明一下,為什么 not var val or 0 是不正確的模式判斷。

首先,not var val 模式指的是對(duì) var 模式取反。var 模式唯一可以取反的情況只有元組判斷的情況。如果一個(gè)引用類型用于解構(gòu),那么此時(shí)的 var 會(huì)優(yōu)先判斷一次 null,畢竟對(duì)象不為 null 才可以進(jìn)行對(duì)象解構(gòu)。因此,這是唯一一種可以用 not var 的情況。但是,很顯然這里的 is not var val 并非解構(gòu),它的 val 是一個(gè)臨時(shí)變量,因此,not var val or 0 這個(gè)模式就永遠(yuǎn)不可能成立:因?yàn)?var val 是必然成立的賦值過(guò)程。

其次,就算我們退一萬(wàn)步講,not var val 我們暫且不考慮賦值成功與否,or 代表的是兩者至少有一個(gè)成立就可以。那么,如果我們假設(shè) or 右側(cè)的常量模式 0 成立的話,那么左邊的 not var val 可能就不一定成立了。注意,這里我們要說(shuō)“不一定成立”,是因?yàn)槲覀兺肆艘蝗f(wàn)步在說(shuō)明這個(gè)道理,這里是一個(gè)假設(shè)說(shuō)明。那么,一旦這樣的 var 模式不成立,我們就無(wú)法讓編譯器斷定,這個(gè) val 是否能在代碼后面繼續(xù)使用了。那么這里的 val 的聲明就無(wú)法確??捎眯?。且不說(shuō)編譯器無(wú)法確定,就是你,在寫代碼的時(shí)候也不能確保能安全使用該變量。因此,對(duì)于聲明模式和 var 模式下,這兩種模式由于都會(huì)產(chǎn)生新的臨時(shí)變量,因此為確保編譯器可以正確知道變量的使用范圍,我們不能將這兩種模式放在 or 的兩側(cè)的其中一邊。

那么,上面的代碼也不是沒(méi)有辦法去做。你只需要將原始的模式加上小括號(hào),然后在小括號(hào)左邊加 not 表示對(duì)整個(gè)模式取反即可。

這就可以了。這樣編譯器就知道,你在匹配 var val and not 0 模式。當(dāng)不滿足的時(shí)候,if 條件成立,直接 return;反之,var val and not 0 模式成立,于是 val 變量可以安全正確使用。

當(dāng)然,這里需要你打上小括號(hào)。因?yàn)?not 優(yōu)先級(jí)最前,它是單模式的運(yùn)算,不打括號(hào)會(huì)被視為 not var valnot 0 兩個(gè)模式的 and 連接,導(dǎo)致錯(cuò)誤:not var val 是不可能成立的。

10、純棄元不可單獨(dú)使用

前文簡(jiǎn)要介紹過(guò)棄元模式的用法和范疇,不過(guò)棄元模式是可以直接運(yùn)用到邏輯模式里的:

只要在模式匹配期間出現(xiàn)了一個(gè) var _ 或者別的什么模式,就可以直接使用純棄元 _。當(dāng)然,這么寫沒(méi)有意義,因?yàn)槭侨哂嗟哪J狡ヅ洌ㄋ裁炊紱](méi)有判定),只是說(shuō)可以這么用——編譯器認(rèn)為不是錯(cuò)誤的語(yǔ)法,就沒(méi)有必要去限制它。

C# 邏輯與括號(hào)模式的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
轮台县| 仲巴县| 确山县| 安义县| 广州市| 多伦县| 武安市| 汾西县| 乐东| 永年县| 塘沽区| 汉寿县| 四川省| 武威市| 特克斯县| 靖远县| 长顺县| 古蔺县| 平罗县| 湾仔区| 丰原市| 保德县| 郑州市| 临城县| 奈曼旗| 阜宁县| 新竹市| 丰顺县| 灵宝市| 大名县| 洞头县| 深州市| 科技| 渭源县| 英超| 陇南市| 虎林市| 乐业县| 甘孜| 泰州市| 灌阳县|