I was wondering if you can add something like a "null-safe"-operator in F#. I know that there might be plans for such an operator in C# for the next bigger release.
If there is no way to achieve such a behaviour, is there a way to wrap a statement that possibly could throw a NullReferenceException
into a block that catches the exception and just returns null
.
I thought of something like:
let sth = %% <@ someobject.method().another().andAnother() @>
where %%
is a custom operator that executes the expression and checks for the exception.
One Attempt I made was:
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
let (~%%) (right:Expr) =
try
right.CompileUntyped()
right()
with
| ex -> null
But this does not do what I wanted (in fact it doesn't even compile :)
I read through:
Does anyone have ideas how to elegantly create such a one-line try-catch for chained methods?
I do not think you can implement something like the .?
operator proposed for C# in a practically useful and syntactically convenient way for F# as a library feature. Although, I think it would be a very useful language extension, so I'd submit it to the F# user voice and perhaps submit a pull request :-).
Exception handling. Your code sample is not quite doing the same as C#, because you are just handling arbitrary exceptions. The point of the C# feature is that it inserts null
checks after each .
- you could do that by transforming the quotation and then compiling it, but the compilation is going to be slow. Your function could really just be:
let orNull f = try f () with :? NullReferenceException -> null
And then you can write
orNull <| fun () -> x.Foo().Bar()
.. but as mentioned earlier, this is just wrapping code in a standard try
block and it handles exceptions, so it is not going to be doing the same thing as the C# code.
Computation builder. If you wanted a fancier F# solution, you could come up with a computation expression builder that lets you write something like this:
safe { let! a = x.Foo()
let! b = a.Bar()
return b }
This can do the null checks in the same way as the C# .?
operator, but you need a separate binding for each part of the method call chain, so it is a bit more typing. The computation builder inserts a hidden null check in the Bind
member like this:
type NullBuilder() =
member x.Return(v) = v
member x.Bind(v, f) = if (box v) = null then null else f v
let safe = NullBuilder()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With