Wondering if there is an elegant way to accomplish the following:
I have a function that creates a Disposable and returns it as an Option. The caller matches on it. Now, since the wrapped object is bound to inside a match case, I don't know how to do a 'use' style binding inside the match such that the object gets properly disposed.
let createSocket (hostEntry:IPHostEntry) =
let httpPort = 80
let endpoint = new IPEndPoint(hostEntry.AddressList.[0], httpPort)
let socket = new Socket(endpoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
socket.Connect(endpoint)
if (socket.Connected) then Some socket else None
let fetchResource url =
let uri = new System.Uri(url)
let hostEntry = Dns.GetHostEntry(uri.Host)
match createSocket(hostEntry) with
| Some socket ->
use s = socket // More elegant way?
sendRequest s uri.Host uri.PathAndQuery |> getResponse
| None ->
"Failed to open socket"
You have a using
function available in core library, but it's up to you whether you consider this more elegant:
match createSocket(hostEntry) with
| Some socket ->
using socket <| fun s ->
sendRequest s uri.Host uri.PathAndQuery |> getResponse
| None ->
"Failed to open socket"
You can take it a step further and package the whole trick in a single function:
module Option =
let using func = Option.bind (fun disp -> using disp func)
...
createSocket(hostEntry)
|> Option.using (fun s ->
sendRequest s uri.Host uri.PathAndQuery |> getResponse)
// handle None however you like
|> function Some x -> x | None -> "Failed to open socket"
Though I don't remember I've ever felt the need to do so personally.
I think null
is most elegant here.
if socket.Connected then socket else null
...
use s = createSocket(hostEntry)
if s = null then
"Failed..."
else
sendRequest...
use
can properly handle (ignore) null. That said, I didn't find the original code particularly inelegant to start.
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