我正在读“专业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在过去引起了很多悲痛。
答案 0 :(得分: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>
作为参数时,您必须明确检查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
。
答案 1 :(得分:5)
要添加Tomas的答案,Option
类型的一个主要好处在于它支持的高阶函数,它可以提供更多的简洁性和安全性。您可能会在主题上找到my blog post。