2017-01-29 7 views
6

Zastanawiasz się, czy jest elegancki sposób, aby wykonać następujące czynności:wiążące jednorazowego obiektu stosowanie stylu powrócił jako opcja

Mam funkcji, która tworzy jednorazowe i zwraca go jako opcja. Dzwoniący dopasowuje się do niego. Teraz, ponieważ zawinięty obiekt jest związany z wewnątrz przypadku dopasowywania, nie wiem, jak wykonać wiązanie stylu "użytkowania" w obrębie dopasowania, aby obiekt został właściwie usunięty.

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" 

Odpowiedz

4

Masz using funkcji dostępnej w bibliotece rdzenia, ale to zależy od Ciebie, czy uznać to bardziej eleganckie:

match createSocket(hostEntry) with 
| Some socket -> 
    using socket <| fun s -> 
     sendRequest s uri.Host uri.PathAndQuery |> getResponse 
| None -> 
    "Failed to open socket" 

Można zgłosić się o krok dalej i zapakować cały trick w pojedyncza funkcja:

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" 

Chociaż nie pamiętam, że kiedykolwiek odczuwałem potrzebę zrobienia tego osobiście.

3

Uważam, że najbardziej elegancki jest tutaj null.

if socket.Connected then socket else null 

... 

use s = createSocket(hostEntry) 
if s = null then 
    "Failed..." 
else 
    sendRequest... 

use może prawidłowo obsługiwać (zignorować) null. To powiedziawszy, nie uważałem początkowego kodu za szczególnie nieelegancki.

+2

Powinieneś unikać porównywania do '' null'' z '' = '' lepiej jest użyć funkcji '' isNull''. – Gustavo

+0

Whoah, dawno nie widzę ... – kvb

0

Twoim problemem jest sama funkcja createSocket. Wewnątrz tej funkcji tworzysz swoją Socket, która implementuje IDisposable i przekazujesz ją zewnętrznemu zakresowi. Powinieneś refaktoryzować, abyś mógł wykorzystać składnię use socket = new Socket(...). Można to zrobić, tworząc klasę opakowującą, która implementuje IDisposable i odpowiednio zbywa gniazdo.

Powiązane problemy