没有比无效更邪恶吗?

Car*_*ngo 27 null f# nullpointerexception

在F#中,它们没有空值并且不想支持它.程序员仍然必须为无类似于C#程序员做出支持!= null.

没有人真的比无效更邪恶吗?

Dar*_*rio 35

问题null在于你几乎可以在任何地方使用它,即引入无效状态,这既不是预期不合理.

拥有一个'a option永远是一个明确的事情.您声明操作可以生成Some有意义的值,或者None编译器可以强制执行以正确检查和处理.

通过劝阻null支持'a option-type,你基本上可以保证程序中的任何值都具有某种意义.如果某些代码设计为使用这些值,则不能简单地传递无效代码,如果有option-type 函数,则必须涵盖所有可能性.

  • 这个答案远远超过了公认的imo(尽管两者都很棒).ShdNx的答案解决了为什么选项很棒但是这个选项真的将它与null进行比较并回答它真的不那么邪恶(甚至太棒了!).希望我能第二次投票; 谢谢达里奥! (2认同)

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数据存储中不存在的人,您认为会发生什么?

  • 该函数是否会抛出NotFound异常?
  • 它会返回null吗?
  • 如果他们不存在,它会创造这个人吗?

如果没有阅读代码(如果你有权访问它),阅读文档(如果有人写得很好),或者只是调用函数,你就无从知晓了.这基本上是空值的问题:它们看起来和行为就像非空值一样,至少在运行时之前.

现在让我们说你有一个带有这个签名的函数:

val getPersonByName : (name : string) -> option<Person>
Run Code Online (Sandbox Code Playgroud)

这个定义使得它非常明确地发生了什么:你要么让一个人回来,要么你不会,这种信息是在函数的数据类型中传达的.通常,您可以更好地保证处理选项类型的情况而不是潜在的空值.

我会说选项类型比空值更仁慈.