让我说我有这种类型:
type ResultInfo =
| Success
| Error of (HttpStatusCode * string)
和一个返回ResultInfo类型的“结果”的函数
有没有办法做类似的事情:
if result is type Success then ...
因为有时我只想知道类型,并且在只需要快速检查的情况下,match语法可能会有点繁琐
答案 0 :(得分:3)
您不能进行类型测试,因为联合用例不是真正的类型-它是一个联合类型(如C中的联合),带有一个标记,表明它是哪种情况。
这就是为什么您不能做这样的事情:
type MoreSuccess = MoreSuccess of Success //type Success is not defined
因此,您无法执行运行时类型检查。但是,对于实现结构相等的成员,可以直接进行比较。因此,
if result = Success then
printfn "Success!"
else
printfn "Boo"
是完全有效的,并且也清晰易读。
如果您真的想使用if
表达式,则更紧凑的方法是定义一个内联函数,如下所示:
if (function Error _ -> true | _ -> false) result then
printfn "Error"
有趣的是,编译器将生成扩展属性,如IsSuccess
,IsError
,这些属性可以按预期工作,但是,它们是与来自C#和VB等其他语言的DU互操作的好处,很不幸在F#中不可见。
答案 1 :(得分:2)
您可以编写Option.isSome
之类的帮助程序模块
module ResultInfo =
let isSuccess = function
| Success -> true
| Error _ -> false
let isError = function
| Success -> false
| Error _ -> true
if result |> ResultInfo.isSuccess then
...
或将属性/功能附加到您的类型
type ResultInfo =
| Success
| Error of (HttpStatusCode * string)
member self.IsSuccess =
match self with
| Success -> true
| Error _ -> false
if result.IsSuccess then
...
我总是喜欢明确指定所有联合用例,以便通过添加新用例将生成编译器警告。如果仅匹配Success
并用_
处理所有其他并集情况,可能会导致潜在的错误,因为您没有得到编译器警告,甚至可能会忘记处理该情况。
答案 2 :(得分:0)
您可以将字符串值与类似这样的函数进行比较:
let sameStrings ut1 ut2 =
let firstPart (str:string) = str.Split([|' '|])
let nameString = string >> firstPart
nameString ut1 = nameString ut2
然后有一个if语句,例如if sameStrings Success a then
下面的示例用法和输出(请注意,这不会比较实际的错误值,但是如果您想执行此操作,则应该只能使用字符串比较):
type ResultInfo =
| Success
| Error of (int * string)
let printSameAs ut1 ut2 =
printfn "%A - match %A: %b" ut1 ut2 (sameStrings ut1 ut2)
let a = Success
let b = Error (404,"Not Found")
printSameAs a Success
printSameAs b Success
printSameAs a (Error (0,""))
printSameAs b (Error (0,""))
有输出:
Success - match Success: true
Error (404, "Not Found") - match Success: false
Success - match Error (0, ""): false
Error (404, "Not Found") - match Error (0, ""): true