Pet*_*ner 4 f# exception-handling operator-overloading quotations nullreferenceexception
我想知道你是否可以在F#中添加类似"null-safe"-operator的东西.我知道可能有计划在C#中为这样一个运营商提供下一个更大的版本.
如果没有办法实现这样的行为,是否有办法包装一个可能会抛出一个NullReferenceException
捕获异常并返回的块的语句null
.
我想到了类似的东西:
let sth = %% <@ someobject.method().another().andAnother() @>
Run Code Online (Sandbox Code Playgroud)
其中%%
是执行表达式并检查异常的自定义运算符.
我做的一个尝试是:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
let (~%%) (right:Expr) =
try
right.CompileUntyped()
right()
with
| ex -> null
Run Code Online (Sandbox Code Playgroud)
但这不符合我的要求(事实上它甚至没有编译:)
我通读了:
有没有人有想法如何优雅地为链式方法创建这样的单行try-catch?
我不认为你可以.?
用一种实用的,语法上方便的方式为C#实现类似C#的操作符,作为库的一个特性.虽然,我认为这将是一个非常有用的语言扩展,所以我将它提交给F#用户语音,并可能提交拉取请求 :-).
异常处理.您的代码示例与C#完全不同,因为您只是处理任意异常.C#功能的要点是它在每次之后插入 null
检查.
- 你可以通过转换引号然后编译它来做到这一点,但编译会很慢.你的功能可能只是:
let orNull f = try f () with :? NullReferenceException -> null
Run Code Online (Sandbox Code Playgroud)
然后你就可以写了
orNull <| fun () -> x.Foo().Bar()
Run Code Online (Sandbox Code Playgroud)
..但如前所述,这只是将代码包装在标准try
块中并处理异常,因此它不会像C#代码那样做.
计算生成器.如果你想要一个更好的F#解决方案,你可以想出一个计算表达式构建器,它允许你写这样的东西:
safe { let! a = x.Foo()
let! b = a.Bar()
return b }
Run Code Online (Sandbox Code Playgroud)
这可以像C#.?
操作符一样进行空检查,但是您需要为方法调用链的每个部分单独绑定,因此它需要更多的输入.计算构建器在Bind
成员中插入隐藏的空检查,如下所示:
type NullBuilder() =
member x.Return(v) = v
member x.Bind(v, f) = if (box v) = null then null else f v
let safe = NullBuilder()
Run Code Online (Sandbox Code Playgroud)