来自Exceptions(抛出和捕获的语法),它说F#内置了四个有用的异常关键字,其中nullArg
会抛出NullArgumentException
:
let f x =
if x then "ok"
else nullArg "paramName" "message"
如果我只为 F# 编写模块,那么什么时候应该引发 NullArgumentException
?
来自Exceptions(抛出和捕获的语法),它说F#内置了四个有用的异常关键字,其中nullArg
会抛出NullArgumentException
:
let f x =
if x then "ok"
else nullArg "paramName" "message"
如果我只为 F# 编写模块,那么什么时候应该引发 NullArgumentException
?
Result
类型。这包括读取可能存在格式不正确(因为它来自用户)或验证可能不正确的用户输入数据。nullArg
特别地,由于F#大部分消除null
值,所以你并不需要太多情况,但是当您将.NET类型作为参数时,仍然可能遇到它。如果您有一个函数接受IDictionary<string, string>
,并且您从不希望它为null
,可以编写:let lookupName (dict:IDictionary<string, string>) =
if dict = null then nullArg "dict" "lookupName expects a valid dictionary!"
if dict.ContainsKey "name" then dict.["name"] else "anonymous"
IDictionary
永远不会为null
。如果在代码中不小心出错,明确处理这种情况可能会提供更有用的错误信息。你不应该使用异常。异常很烦人,尽量避免使用。只有在与期望你抛出异常或没有其他报告错误的方式的外部代码进行接口时才使用它们。
相反,如果你正在编写可能失败的函数,请使其返回一个“两者之一”的值 - 要么是结果,要么是错误。可以参考以下方式:
type Result<'t, 'e> = Ok of 't | Error of 'e
let f x =
if x then Ok "ok"
else Error "boo!"
Result
类型(以及一些有用的实用程序)。查看该帖子中的示例。
Result
类型。一旦你学会了F#,并且知道何时使用异常比Result
类型更有用(这很少见,但偶尔会发生),那么只有在那时你才应该遵循Tomas的建议。 - rmunnResult
显然是最好的选择,但在Tomas描述的空参数情况下,返回Result
没有任何好处,只会污染你的API。你只想要一个有用的错误信息来使调用者修复他们的代码。 - TheInnerLightnullArg
的场合。但是如果你处于一般的.NET领域(这里并不是这种情况),那么请按照罗马人的做法去做。 - Fyodor SoikinnullArg
,它非常少用 - 我选择IDictionary
只是作为一个非常有用的 .NET 类型的例子。更一般地说,如果“无效结果”不是您预期的公共 API 的正常部分,那么在所有类型中污染Result
是一个错误。 - Tomas Petricek