共用方式為


Null 值

本主題描述如何在 F# 中使用 Null 值。

F# 9 之前的 Null 值

Null 值通常不會用於 F# 中的值或變數。 不過,在某些情況下,Null 會顯示為異常值。 如果類型是在 F# 中定義,除非將 AllowNullLiteral 屬性套用至類型,否則不允許 null 做為一般值。 如果類型是以其他 .NET 語言定義,則 Null 是可能的值,而且當您與這類類型互通時,F# 程式代碼可能會遇到 Null 值。

對於在 F# 中定義的類型,並且嚴格使用 F# 使用,直接 使用 F# 連結庫建立 Null 值的唯一方法是使用 unchecked.defaultofArray.zeroCreate。 不過,對於來自其他 .NET 語言使用的 F# 類型,或如果您使用該類型搭配未以 F# 撰寫的 API,例如 .NET Framework,就可能發生 Null 值。

在其他 .NET 語言中使用可能包含 Null 值的參考變數時,在 F# 中可以使用 option 類型。 在 F# option 類型中,如果沒有物件,你應該使用選項值 None。 當有物件時,您應搭配物件 obj 使用選項值 Some(obj)。 如需詳細資訊,請參閱 選項。 請注意,如果 Some x,您仍然可以將 null 值封裝到 Option 中,x 恰好 null。 因此,當值 null時,請務必使用 None

null 關鍵詞是 F# 中的有效關鍵詞,當您使用以其他 .NET 語言撰寫的 .NET Framework API 或其他 API 時,您必須使用它。 當您在呼叫 .NET API 時,可能需要使用空值的兩種情況是:一是將空值作為引數傳遞,二是解釋 .NET 方法呼叫的傳回值或輸出參數。

若要將 Null 值傳遞至 .NET 方法,只要在呼叫程式代碼中使用 null 關鍵詞即可。 下列程式代碼範例說明這點。

open System

// Pass a null value to a .NET method.
let ParseDateTime (str: string) =
    let (success, res) =
        DateTime.TryParse(str, null, System.Globalization.DateTimeStyles.AssumeUniversal)

    if success then Some(res) else None

若要解譯從 .NET 方法取得的 Null 值,如果可以的話,請使用模式比對。 下列程式代碼範例示範如何使用模式比對來解譯從 ReadLine 傳回的 null 值,當它嘗試讀取到輸入數據流結尾時。

// Open a file and create a stream reader.
let fileStream1 =
    try
        System.IO.File.OpenRead("TextFile1.txt")
    with :? System.IO.FileNotFoundException ->
        printfn "Error: TextFile1.txt not found."
        exit (1)

let streamReader = new System.IO.StreamReader(fileStream1)

// ProcessNextLine returns false when there is no more input;
// it returns true when there is more input.
let ProcessNextLine nextLine =
    match nextLine with
    | null -> false
    | inputString ->
        match ParseDateTime inputString with
        | Some(date) -> printfn "%s" (date.ToLocalTime().ToString())
        | None -> printfn "Failed to parse the input."

        true

// A null value returned from .NET method ReadLine when there is
// no more input.
while ProcessNextLine(streamReader.ReadLine()) do
    ()

F# 類型的 Null 值也可以透過其他方式產生,例如當您使用 Array.zeroCreate時,它會呼叫 Unchecked.defaultof。 您必須小心使用這類程式碼,以保持空值被封裝。 在僅供 F# 使用的連結庫中,您不需要檢查每個函式中的 Null 值。 如果您要撰寫函式庫以與其他 .NET 語言互操作,您可能必須新增 null 輸入參數的檢查,並拋出 ArgumentNullException,就像您在 C# 或 Visual Basic 程式代碼中所做的一樣。

您可以使用下列程式代碼來檢查任意值是否為 Null。

match box value with
| null -> printf "The value is null."
| _ -> printf "The value is not null."

從 F# 9 開始的 Null 值

在 F# 9 中,語言新增了額外的功能來處理可以將 null 作為值的參考型別。 這些預設為關閉 - 若要開啟它們,必須將下列屬性放在您的項目檔中:

<Nullable>enable</Nullable>

這會將 --checknulls+旗標 傳遞至 F# 編譯程式,併為組建設定 NULLABLE預處理器指示詞

若要明確地選擇支援可為 Null 的特性,必須在類型宣告中添加新的語法後綴:

type | null

條形符號 | 在語法中表示邏輯 OR,它構建了兩個不相交的類型集合的聯集:基礎類型和可空引用。 這是相同的語法記號,用於宣告 F# 歧視聯集的多種類型:type AB = A | B 具有 AB的意義。

可為 Null 的註解 | null 可用於通常使用參考型別的所有位置:

  • 等位類型、記錄類型和自定義類型的欄位。
  • 為現有類型創建的別名。
  • 泛型型別的類型應用程式。
  • 對 let 綁定、參數或回傳型別添加明確的型別註解。
  • 將型別標註應用於物件導向程式設計的結構,例如成員、屬性或欄位。
type AB = A | B
type AbNull = AB | null

type RecordField = { X: string | null }
type TupleField = string * string | null

type NestedGenerics = { Z : List<List<string | null> | null> | null }

條形符號 | 在 F# 中有其他用法,這可能會導致語法模棱兩可。 在這種情況下,在註記為空的型別周圍需要括號:

// Unexpected symbol '|' (directly before 'null') in member definition
type DUField = N of string | null

將相同類型包裝成一對 ( ) 括弧可修正此問題:

type DUField = N of (string | null)

在模式比對中使用時,| 用來分隔不同的模式比對子句。

match x with
| ?: string | null -> ...

此程式碼片段實際上等同於先對 string 類型進行類型測試,然後有一個獨立的子句來處理 null。

match x with
| ?: string 
| null -> ...

重要

額外的 Null 相關功能已新增至語言,以達到互操作性的目的。 在 F# 類型建模中使用 | null 並不被認為是表示遺漏資訊的慣常做法,為了達到這個目的,請使用選項(如上所述)。 若要深入瞭解與 null 相關的 慣例,請參閱樣式指南中的

另請參閱