5 3 2 使用可選值

2021-08-25 19:15:41 字數 2199 閱讀 3251

5.3.2 使用可選值

到目前為止,我們已經看到如何宣告差別聯合型別,以及如何使用識別器建立值。現在,我們將學習如何編寫**,讀取值。看過之後f# 示例之後,我們將在 c# 中實現相同的**,使用我們前面提到過的 tag 屬性的表示形式。

在 f# 中匹配差別聯合

當使用差別聯合時,我們總是要為所有可能的選項編寫**,因為,我們不知道這個值到底表示哪乙個。加快一下早先的類似情況, 我們必須測試列表是空列表。還是 cons cell。我們使用模式匹配來完成此操作:match 構造使我們能夠根據幾種模式測試值。我們可以用相同的功能,處理差別聯合,這一次,除了識別器寫模式。清單 5.5 顯示了乙個示例,獲取下一計畫事件的發生。

listing 5.5 calculating the next occurrence of an event (f#)

let getnextoccurrence(schedule) =

match schedule with

| never -> datetime.maxvalue

| once(eventdate) –>

if (eventdate > datetime.now) then eventdate

else datetime.maxvalue

| repeatedly(startdate, interval) –>

let secondsfromfirst = (datetime.now - startdate).totalseconds

let q = secondsfromfirst / interval.totalseconds

let q = max q 0.0

startdate.addseconds

(interval.totalseconds * (math.floor(q) + 1.0))

這個示例是有點複雜,但它展示了典型的 f# 程式結構。我們使用標準 .net datetime 和 timespan 結構處理日期和時間。我們使用模式匹配測試已為我們選擇了哪乙個計畫。在第一種情況中,我們返回 datetime.maxvalue,這是乙個特殊值,我們用來表示事件在任意未來的日期內都沒有計畫。在第二種情況,我們返回的事件的日期,如果它還沒有發生。最後一種情況(重複事件)更複雜,我們首先計算事件在過去發生了多少次,並返回下一次發生。你可以看到,我們在**中兩次宣告 q 值,這稱為隱藏值,如果我們想把複雜的計算拆成兩個或多個步驟,這是很有用的,可以確保我們不會意外地使用中間值。

如你所見,該模式用於測試乙個值是否值匹配特定的鑑別器,與我們已經用於構造值是完全相同的。模式也提取儲存的值作為引數值,並將它們分配給新的值(分別是 eventdate 和 帶 interval 的 startdate ),這樣,我們就可以立即使用它們。

在 c# 中模仿差別聯合

接下來,我們將看看在 c# 中相同的功能實現。我們早先已經提到有關涉及到的類,因此,假設它們已經實現,且只看使用它們的**。在本章後面,我們將看另乙個有關可選值的示例,包括完整的 c# 實現,因此,您將看到如何編寫 c# 類層次結構,具有相同的屬性,像 f# 的差別聯合一樣。

提示在我們看清單 5.6 的 c# 版本示例之前,有一件重要的事情要注意。有一種情況,當我們已經有類層次結構表示實現的計畫(例如,在乙個共享庫),它並不包含獲取下一次發生的方法。我們需要新增新的功能到應用程式中的模組,不能輕鬆地將虛方法新增到類的基類 schedule。此外,我們要保持這個功能在**中的乙個單獨的地方,保持與這個計算相關的一切,同乙個地方,同乙個檔案中。

listing 5.6 calculating the next occurrence of an event (c#)

datetime getnextoccurrence(schedule schedule)

}c# 版本中所使用的演算法與 f# 版本是一樣的,那麼,唯一的區別我們是如何區分選項,以及如何讀取儲存在選項中的值。在 f# 中,是用模式匹配實現的。在 c# 版本,我們使用 switch,這是 c# 的類似於 f# 中的 match 結構。這是可能的,因為我們已在基類中有 tag 屬性,和乙個列舉,它告訴我們物件表示什麼種類的計畫。否則,我們將必須使用有乙個動態型別測試序列的 if 語句。另外,讀取值,在 f# 中自動完成,現在是有點困難。我們必須轉換計畫到具體的類,以讀取它的屬性。

實際上,對於差別聯合,c# 版本的**是非常接近於f# 編譯器所使用的 .net 表示。這意味著,前面的兩個示例編譯後基本上相同。不過,函式程式設計更強調這種資料型別,這就是為什麼在 f# 中,更容易寫此**。

Option可選值可選值(二)

playground noun a place where people can play import cocoa varstr1 供選鏈結和強制拆包的不同。class person class residence subscript i int room func printnumberofro...

Optional Values可選值簡述

var str string 乙個基礎型別在沒有初始值的時候是不能使用的,而optional value在未經初始化的時候值為nil,nil代表值缺失。varstr string hello vars string str 錯誤,不能將可選量 str直接賦值給 svar s string str 正...

Option可選值(一)

playground noun a place where people can play import cocoa class person class residence subscript i int room func printnumberofrooms var address addre...