Exception handling 如何在F中实现空安全运算符#
我想知道您是否可以在F#中添加类似于“null-safe”运算符的内容。我知道,在下一个更大的版本中,可能有计划在C#中设置这样一个运营商 如果没有办法实现这种行为,那么有没有办法将可能抛出Exception handling 如何在F中实现空安全运算符#,exception-handling,f#,operator-overloading,nullreferenceexception,quotations,Exception Handling,F#,Operator Overloading,Nullreferenceexception,Quotations,我想知道您是否可以在F#中添加类似于“null-safe”运算符的内容。我知道,在下一个更大的版本中,可能有计划在C#中设置这样一个运营商 如果没有办法实现这种行为,那么有没有办法将可能抛出NullReferenceException的语句包装到捕获异常并仅返回null的块中 我想到了这样的事情: 但这并不是我想要的(实际上它甚至没有编译:) 我通读了: 还有更多的msdn文档 有人知道如何为链式方法优雅地创建这样一行try-catch吗?我不认为您可以实现类似于为C提出的?操作符的东
NullReferenceException
的语句包装到捕获异常并仅返回null
的块中
我想到了这样的事情:
但这并不是我想要的(实际上它甚至没有编译:)
我通读了:
- 还有更多的msdn文档
有人知道如何为链式方法优雅地创建这样一行try-catch吗?我不认为您可以实现类似于为C提出的
?
操作符的东西,以一种实用且语法方便的方式将F作为库特性。尽管如此,我认为它将是一个非常有用的语言扩展,所以我将把它提交给
异常处理。您的代码示例与C#做得不太一样,因为您只是在处理任意异常。C#特性的要点是,它在每次
检查后插入null
检查-您可以通过转换引号然后编译它来实现这一点,但编译速度会很慢。您的功能实际上可以是:
let orNull f = try f () with :? NullReferenceException -> null
然后你就可以写了
orNull <| fun () -> x.Foo().Bar()
这可以用与C#?
操作符相同的方式执行空检查,但是您需要为方法调用链的每个部分单独绑定,因此需要更多的类型。计算生成器在Bind
成员中插入一个隐藏的空检查,如下所示:
safe { let! a = x.Foo()
let! b = a.Bar()
return b }
type NullBuilder() =
member x.Return(v) = v
member x.Bind(v, f) = if (box v) = null then null else f v
let safe = NullBuilder()
type T() =
member this.M(b) = if b then Some this else None
T().M(true)
|> Option.bind (fun t -> t.M(true))
|> Option.bind (fun t -> t.M(false))
|> Option.bind (fun t -> t.M(true))
也许可以使用F#worflows,扩展May monad的概念,并能够写出以下内容:
let sth = maybe { someobject.method().another().another() }
这是一个有趣的问题。幸运的是,仅存在于F#world中的代码(即不使用以其他语言编写的.NET库)并不存在
?
想要解决的普遍问题,因为空性必须是显式的(使用[]
)。但是,这个概念有一个功能性的对应关系:<代码>选项>代码>类型和<代码> BION/COD>函数(<代码> BIN < /代码>是工作流的基础,如托马斯所示)。p>
你可以这样做:
safe { let! a = x.Foo()
let! b = a.Bar()
return b }
type NullBuilder() =
member x.Return(v) = v
member x.Bind(v, f) = if (box v) = null then null else f v
let safe = NullBuilder()
type T() =
member this.M(b) = if b then Some this else None
T().M(true)
|> Option.bind (fun t -> t.M(true))
|> Option.bind (fun t -> t.M(false))
|> Option.bind (fun t -> t.M(true))
并定义一个bind
操作符
let (?>) o f = Option.bind f o
并将其缩短为:
T().M(true)
?> fun t -> t.M(true)
?> fun t -> t.M(false)
?> fun t -> t.M(true)
但是,这样做没有什么价值。它既不简洁也不清晰。然而,我认为这表明:
- 你正在处理的一般概念
- 它本身并不与
null
- 这在函数式语言中通常是如何处理的
try。。抓住。。使用