C 8 0 中的模式匹配

2021-10-03 06:37:38 字數 4956 閱讀 3161

2019-08-162019-08-16 18:01:08

閱讀 1470

多年來,我們在 c# 中實現了許多功能,不僅改善了**的效能,更重要的是還提高了**的可讀性。鑑於軟體行業的快速發展,語言當然需要與其使用者群同步發展。廣泛用於 haskell、swift 或 kotlin 等各種程式語言的某些功能,有時也會用於 c#。其中乙個功能就是模式匹配,這一概念已經存在很長時間,是 .net 領域中的許多開發人員一直期待的功能。

從 c# 7.0 開始,開發人員就體驗到了模式匹配的強大功能。我們見證了模式開始成形,然後變成非常強大且有趣的語言補充的過程。正如其他語言功能徹底改變了軟體編寫方式一樣,我希望 c# 中的模式匹配也會產生類似效果。

不過,我們真的需要另一種語言功能嗎?我們不能就使用傳統方式嗎?當然可以。儘管模式匹配等附加功能肯定會改變許多人編寫**的方式,但對於多年來引入的其他語言功能我們也可以提出同樣的問題。

徹底改變 c# 語言的其中乙個功能就是引入的語言整合查詢 (linq)。現如今處理資料時,人們會按自己的喜好來進行選擇。有些人選擇使用 linq,在某些情況下,使用這種語法構造的**不會那麼冗長,而其他人則會選擇傳統迴圈程式。我預計模式匹配的應用情況也是類似的,因為隨著開發人員逐漸拋棄更為冗長的方法,新功能將改變他們的工作方式。注意,由於許多開發人員會選擇堅持使用經驗證切實可行的解決方案,因此傳統方法不會有什麼發展。但其他語言功能應該會提供一種方法來補充 c# **專案,而不是排斥當前**。

如果你曾經使用過 kotlin 或 swift 等語言,那麼你可能已經見過模式匹配的實際示例。它廣泛應用於市場上各種不同的程式語言。當然,主要是為了使**更具可讀性。那麼什麼是模式匹配?

區分水果型別和水果屬性就是模式匹配的功能。開發人員在進行識別時會使用各種表達方式。

if

(fruit.

gettype()

==typeof

&& fruit.color == color.green)

if

幸運的是,有一種更好的方法。如前所述,使用 swift 和 kotlin 等語言就可以使用模式匹配。就 c# 7.0 而言,它引入了輕量級版本的模式匹配,這很有幫助,儘管它缺乏許多其他語言提供的優秀功能。你可以將上述表示式重構到下方的 c# 7.0 **,這樣你就可以使用 switch 來匹配各種模式。它並不完善,但相較於之前的**確實有所改進。**如下:

switch

(fruit)

圖 1:使用 when 關鍵字來應用篩選器

fruit fruit =

new;

switch

(fruit)

如圖 1 所示,順序至關重要。我先尋找顏色為綠的蘋果,因為這個特徵對我來說是最重要的。如果還有另一種顏色,假設棕色,這表示我的蘋果腐敗了,我想把它扔掉。至於其他蘋果,我不想用來製作派,所以我就吃了。最終的蘋果就是既非綠色也非棕色的所有蘋果。

你還會發現,如果我得到橘子,我就會剝掉橘皮。我並不侷限於處理一種特定型別;只要這些型別都繼承自 fruit,就都可以處理。

其他部分的執行方式與你自 c# 1.0 以來一直使用的普通 switch 相同。這個示例完全是使用 c# 7.0 編寫的,那麼問題來了,還有改進空間嗎?我會說有。**仍然有些冗長,可以通過改進模式的表達方式使其更具可讀性。此外,它還有助於使用其他方法來表達對資料「外觀」的約束。接下來我們討論 c# 8.0,並介紹為使生活更舒適而引入的更改。

最新版本的 c#(目前為預覽版)引入了一些重要的模式匹配改進。若要試用 c# 8.0,必須使用 visual studio 2019 預覽版,或者在 visual studio 2019 中啟用預覽版語言功能.c# 8.0 將於今年下半年正式發布,預計與此同時 .net core 3.0 也將推出。我們如何尋找新的方法來表達對屬性型別的約束?我們如何使塊模式的表示式更為直觀、可讀性更強?在 c# 8.0 中,該語言又向前邁進了一步,引入了可與各種模式配合使用的方法,而使用過 kotlin 等語言的人應該非常熟悉這些模式。這些都是使**可讀且可維護的附加功能。

首先,我們現在可以使用稱為 switch 表示式的**,而不是開發人員自 c# 1.0 以來就一直使用的傳統 switch 語句。下面是 c# 8.0 中 switch 表示式的示例:

var whatfruit = fruit switch

;

這不僅僅是儲存字元。請考慮這種可能性。例如,我現在可以引入表示式體成員,其中包含這些 switch 表示式中的某乙個,它還利用了模式匹配的強大功能,如下所示:

public fruit fruit 

public string whatfruit => fruit switch

;

**會變得非常有趣且功能強大。以下**展示你會如何以傳統方式執行此模式匹配。看一看,然後選定更喜歡的那個**:

public string whatfruit

return;}

}

顯然,這是乙個非常簡單的場景。假設引入約束時,我要匹配多個型別,然後在條件上下文中使用強制轉換型別。已經對這個想法感興趣了?我想也是!

bool? visible =

false

;var visibility = visible switch

;

這段**表示,你為乙個可為 null 的布林值使用了四個事例,這種用法當然是錯誤的。試著注意如何使用 switch 表示式,並且就像使用任何其他語言功能一樣,不要濫用語法。

我已經介紹了 switch 表示式可以減少**編寫量並使**更具可讀性這一事實。這一點在為型別新增約束時也是如此。如果你檢視元組、解構和所謂的遞迴模式的組合,c# 8.0 中對模式匹配的更改就會非常明顯。

遞迴模式是指乙個模式匹配的表示式的輸出變為另乙個模式匹配的表示式的輸入。這意味著解構物件,並檢視物件型別、物件型別的屬性、物件型別的屬性的型別等的表達方式,然後應用所有上述內容的匹配。這看似複雜,但實際上並不複雜。

接下來介紹一種不同型別及其結構。在圖 2 中,你將看到繼承自 shape 的 rectangle。shape 只是乙個引入了屬性點的抽象類,而屬性點是將 shape 放到表面上的方法,通過它我就知道所放置的位置。

圖 2 解構示例

abstract class

shape

}class

rectangle

: shape

public int height

public

void

deconstruct

(out int width, out int height, out point point)

}

因此,我基本上有三種在 c# 8.0 中表達模式的新方法,而且每種方法都有特定用例。它們是:

位置模式使用你的類上的解構方法。你可以表達與給定值相匹配的模式,而該值是通過解構獲取的。鑑於你定義了解構 rectangle 的方法,你可以表達乙個模式,該模式使用輸出(圖 3 中所示)的位置。

圖 3 位置模式

shape shape =

newrectangle};

var result = shape switch

;

首先,匹配 shape 的型別。在此示例中,我只想將其與 rectangle 匹配。第二個應用的模式在與 rectangle 匹配時,配合使用解構方法和元組語法來表達我在每個特定位置所需要的值。

我可以指定我明確希望該點為 null,或者可以使用下劃線來表達我根本不在意。記住,此處順序非常重要。如果在我們的版本中我們並不在意頂點,那麼無論 rectangle 是否具有點,它始終都會與該模式匹配。這稱為位置模式。

如果可以使用析構函式,這就非常方便,即使析構函式輸出很多值,導致變得相當冗長。這就是屬性模式發揮作用的點。到目前為止,我已經匹配了各種型別,但某些場景要求匹配 state 等其他型別,或者要求只檢視各種屬性值或其中缺少的屬性值。

如以下**所示,只要我獲得的結果與包含點的型別匹配(其中這個點的 y 屬性值為 100),我並不在意結果的型別:

shape switch

}=>

"y is 100"

,=>

"point not initialized",}

;

注意,**實際上並不處理 shape 為空或點已初始化但 y 值不為 100 的情況。在這些情況下,這個**會引發異常。這可以通過使用下劃線引入預設事例來解決。

我還可以確切地說,我需要該點未進行初始化,並且我只處理那些未初始化的場景。這比使用位置模式要簡潔得多,而且在無法向所匹配型別新增解構方法的情況下,非常有效。

圖 4 元組模式

var newstate =

(state, operation, key.isvalid)

switch

;

圖 4 中的**先構造新元組,其中包含當前狀態、所需操作以及檢查使用者是否擁有有效金鑰的布林值。這是乙個非常簡單的場景。

根據這些不同的值,我可以通過構造更多的元組以及乙個位置模式來匹配不同的情況。這就是元組模式。如果我嘗試開啟關著但沒有鎖著的門,就會產生新的狀態,告知門現在是開著的。如果門是鎖著的,並且我嘗試用無用的鑰匙來開門,門就會繼續鎖著。如果我嘗試開啟開著的門,我就會收到乙個異常。您明白了吧ўј這是一種非常靈活且有趣的方法,可用於處理前文中**非常冗長且畸形冗長導致可讀性過差的情況。

c# 8.0 中的模式匹配改進,以及 switch 表示式,確實會改變開發人員編寫應用程式的方式。c# 已有近 20 年的歷史,它的演變過程反映了應用程式的生成方式。模式匹配僅僅是這一演變過程中最新的表示式。

對於開發人員而言,避免過度使用這些新原則和模式是明智之舉。注意你所編寫的**,並確保可讀性、可理解性和可維護性都良好。以上就是其他開發人員請求的內容,並且我認為對語言的這些更改將有助於提高你所編寫**的訊雜比。

C 8 0中的索引和範圍

c 8.0中的索引和範圍為訪問序列中的單個元素或範圍提供了簡潔的語法 system.index 型別可用於編制索引。可從 int 建立乙個從開頭開始計數的索引,也可使用字首 運算子 c 建立乙個從末尾開始計數的索引。0表示序列的length,所以 1才是序列的最後乙個數 所以如果直接使用a 0 效果...

C 8 0 範圍型別 Range Type

目錄範圍型別 替代substring方法 我們最原始的 如下 static void main string args for int i 1 i 3 i console.readline 這裡我們顯示的定義了我們查詢陣列的索引1 3,並輸出他們的值。毫無疑問,當我們執行程式之後,結果如下 item...

C 8 0新特性介紹

c 語言是在2000發布的,至今已正式發布了7個版本,每個版本都包含了許多令人興奮的新特性和功能更新。同時,c 每個版本的發布都與同時期的 visual studio 以及 net 執行時版本高度耦合,這也有助於開發者更好的學習掌握 c 並將其與 visual studio 以及 net 的使用結合...