选项

如果命名值或变量可能不存在实际值,则使用 F# 中的选项类型。 选项具有基础类型,可以保存该类型的值,或者它可能没有值。

言论

以下代码演示生成选项类型的函数。

let keepIfPositive (a: int) = if a > 0 then Some(a) else None

可以看到,如果输入 a 大于 0,则生成 Some(a)。 否则,会生成 None

当选项没有实际值时,将使用值 None。 否则,表达式 Some( ... ) 为选项指定一个值。 SomeNone 的值在模式匹配方面非常有用,如以下函数 exists,如果选项具有值,则返回 true,如果选项没有值,则返回 false

let exists (x: int option) =
    match x with
    | Some(x) -> true
    | None -> false

使用选项

搜索不返回匹配结果时,通常使用选项,如以下代码所示。

let rec tryFindMatch pred list =
    match list with
    | head :: tail -> if pred (head) then Some(head) else tryFindMatch pred tail
    | [] -> None

// result1 is Some 100 and its type is int option.
let result1 = tryFindMatch (fun elem -> elem = 100) [ 200; 100; 50; 25 ]

// result2 is None and its type is int option.
let result2 = tryFindMatch (fun elem -> elem = 26) [ 200; 100; 50; 25 ]

在前面的代码中,以递归方式搜索列表。 函数 tryFindMatch 采用谓词函数 pred,该函数返回布尔值和要搜索的列表。 如果找到满足谓词的元素,则递归结束,函数在表达式 Some(head)中返回值作为选项。 当空列表匹配时,递归结束。 此时找不到值 head,并返回 None

许多 F# 库函数在集合中搜索可能或可能不存在的值都会返回 option 类型。 按照约定,这些函数以 try 前缀开头,例如 Seq.tryFindIndex

如果值可能不存在,则选项也很有用,例如,尝试构造值时可能会引发异常。 下面的代码示例对此进行了说明。

open System.IO

let openFile filename =
    try
        let file = File.Open(filename, FileMode.Create)
        Some(file)
    with ex ->
        eprintf "An exception occurred with message %s" ex.Message
        None

上一示例中的 openFile 函数具有类型 string -> File option,因为它在文件成功打开时返回 File 对象,并在发生异常时 None。 根据具体情况,捕获异常而非允许其传播可能并不是一个合适的设计选择。

此外,仍然可以将 null 或 NULL 值传递给选项的 Some 情况。 这通常是要避免的,通常处于例程 F# 编程中,但由于 .NET 中的引用类型的性质,这有可能。

选项属性和方法

选项类型支持以下属性和方法。

属性或方法 类型 描述
None 'T option 创建具有 None 值的选项值的静态成员。
IsNone bool 如果选项具有 None 值,则返回 true
IsSome bool 如果选项具有不 None的值,则返回 true
Some 'T option 一个静态成员,用于创建一个选项,其值不是 None
'T 返回基础值,如果值为 None,则抛出 System.NullReferenceException

Option 模块

有一个模块(Option)包含对选项执行操作的有用函数。 某些函数重复属性的功能,但在需要函数的上下文中非常有用。 Option.isSomeOption.isNone 都是测试选项是否保留值的模块函数。 Option.get 用于获取值(如果存在)。 如果没有值,则会引发 System.ArgumentException

如果存在值,则 Option.bind 函数对值执行函数。 该函数必须恰好采用一个参数,其参数类型必须是选项类型。 函数的返回值是另一种选项类型。

选项模块还包括对应于可用于列表、数组、序列和其他集合类型的函数的函数。 这些函数包括 Option.mapOption.iterOption.forallOption.existsOption.foldBackOption.foldOption.count。 这些函数允许使用选项,例如零个或一个元素的集合。 有关详细信息和示例,请参阅 列表中集合函数的讨论。

转换为其他类型

选项可以转换为列表或数组。 当选项转换为其中任一数据结构时,生成的数据结构包含零个或一个元素。 若要将选项转换为数组,请使用 Option.toArray。 若要将选项转换为列表,请使用 Option.toList

通过提供默认值来转换选项

除了转换为列表和数组之外,还可以使用 Option.defaultValue 函数提供默认值,从而将选项转换为其他类型的选项。 当您想要确保该值不是 None时,这特别有用。 例如:

let optionString = Some("F#")
let defaultString = optionString |> Option.defaultValue ""
// defaultString is "F#"

let optionInt = None
let defaultInt = optionInt |> Option.defaultValue 0
// defaultInt is 0

使用 Option.defaultValue 函数可以无缝处理 SomeNone 事例,而无需模式匹配。

另请参阅