Car*_*ngo 27 null f# nullpointerexception
在F#中,它们没有空值并且不想支持它.程序员仍然必须为无类似于C#程序员做出支持!= null.
没有人真的比无效更邪恶吗?
Dar*_*rio 35
问题null在于你几乎可以在任何地方使用它,即引入无效状态,这既不是预期也不合理.
拥有一个'a option永远是一个明确的事情.您声明操作可以生成Some有意义的值,或者None编译器可以强制执行以正确检查和处理.
通过劝阻null支持'a option-type,你基本上可以保证程序中的任何值都具有某种意义.如果某些代码设计为使用这些值,则不能简单地传递无效代码,如果有option-type 函数,则必须涵盖所有可能性.
Shd*_*dNx 31
当然它不那么邪恶!
如果不检查None,那么在大多数情况下,您的应用程序中会出现类型错误,这意味着它将无法编译,因此它不会因NullReferenceException而崩溃(因为None转换为null).
例如:
let myObject : option<_> = getObjectToUse() // you get a Some<'T>, added explicit typing for clarity
match myObject with
| Some o -> o.DoSomething()
| None -> ... // you have to explicitly handle this case
Run Code Online (Sandbox Code Playgroud)
它仍然可以实现类似C#的行为,但它不太直观,因为你必须明确地说"忽略这可以是无":
let o = myObject.Value // throws NullReferenceException if myObject = None
Run Code Online (Sandbox Code Playgroud)
在C#中,您不必将变量的大小写为null,因此您可能只是忘记进行检查.与上面相同的例子:
var myObject = GetObjectToUse(); // you get back a nullable type
myObject.DoSomething() // no type error, but a runtime error
Run Code Online (Sandbox Code Playgroud)
编辑:斯蒂芬斯文森是绝对正确的,我的示例代码有一些缺陷,写得很匆忙.固定.谢谢!
Jul*_*iet 14
假设我向您展示了这样的函数定义:
val getPersonByName : (name : string) -> Person
Run Code Online (Sandbox Code Playgroud)
如果您传入name数据存储中不存在的人,您认为会发生什么?
如果没有阅读代码(如果你有权访问它),阅读文档(如果有人写得很好),或者只是调用函数,你就无从知晓了.这基本上是空值的问题:它们看起来和行为就像非空值一样,至少在运行时之前.
现在让我们说你有一个带有这个签名的函数:
val getPersonByName : (name : string) -> option<Person>
Run Code Online (Sandbox Code Playgroud)
这个定义使得它非常明确地发生了什么:你要么让一个人回来,要么你不会,这种信息是在函数的数据类型中传达的.通常,您可以更好地保证处理选项类型的情况而不是潜在的空值.
我会说选项类型比空值更仁慈.