我正在读《专业 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:对象引用未设置为对象的实例。 at 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
所以我看不出程序员是如何从 NullPointer 中拯救
出来的PS:NullPointerException过去给我带来了很多悲伤。
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>
作为参数时,您必须显式检查None
和Some
情况。最好使用 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
。你仍然可以编译代码,但在使用 F# 类型时,如果不忽略警告,则不会NullReferenceException
。
另请参阅这篇伟大的,相关的StackOverflow帖子。
为了补充Tomas的答案,Option
类型的一个主要好处在于它支持的高阶函数,这为您提供了更多的简洁性和安全性。您可能会发现我关于该主题的博客文章很有用。