7

我正在阅读《Professional F# 2.0》这本书作者展示了以下代码

let a string : option = None
if a.IsNone then
    System.Console.WriteLine("a is none")
else
    System.Console.WriteLine("a is some");;

然后说

“这使得 Option 的使用大大优于 null 的使用,并且在消除运行时抛出的重要异常来源方面大有帮助”

行。所以我写

System.Console.WriteLine(a.GetType());;

我得到

System.NullReferenceException:对象引用未设置为对象的实例。在 System.Object.GetType() at .$FSI_0008.main@() 由于错误而停止

我就像'un!!!'

真的是怎么做的

if a.isSome then
    do bla bla

any different from

if a != null then
   do bla bla

所以我看不到程序员是如何从 NullPointers 中拯救出来的

PS:NullPointerException 过去让我很伤心。

4

2 回答 2

9

F# 编译器不会完全阻止您NullReferenceException。当您使用 .NET 中定义的类型时,您仍然可以获得null价值,因为 F# 无法阻止这种情况。

但是,当您使用在 F# 中声明的类型时,编译器不允许创建null该类型的值,因此NullReferenceException在这种情况下它会避免。例如,以下代码无法编译:

type Person(name:string) = 
  member x.Name = name

// 'Person' is a type declared in F#, so the argument cannot be 'null' in safe code
let printName (person:Person) = 
  printfn "%s" person.Name

// Compiler error here - 'null' is not a valid value of 'Pereson' type
printName null

当您option<Person>用作参数时,您必须明确检查NoneSome案例。最好使用 来完成此操作match,它会检查您是否没有遗漏任何案例。例如:

let printName (person:option<Person>) = 
  match person with
  // You get a warning here, saying that you're not handling the 'None' case!
  | Some person -> printfn "%s" person.Name

警告告诉您应该添加案例处理None。您仍然可以编译代码,但NullReferenceException如果您不忽略警告,则在使用 F# 类型时将无法获得。

另请参阅这篇很棒的相关 StackOverflow 帖子

于 2012-07-04T13:58:07.267 回答
5

为了补充 Tomas 的答案,Option类型的一个主要好处在于它支持的高阶函数,这给了你更多的简洁性和安全性。您可能会发现我关于该主题的博客文章很有用。

于 2012-07-04T19:09:35.193 回答