2010-04-27 13 views
7

Quindi, data poi seguente codiceCome posso implementare lo stesso comportamento di Dictionary.TryGetValue

type MyClass() = 
    let items = Dictionary<string,int>() 
    do 
    items.Add ("one",1) 
    items.Add ("two",2) 
    items.Add ("three",3) 
    member this.TryGetValue (key,value) = 
    items.TrygetValue (key,value) 
let c = MyClass() 

let d = Dictionary<string,int>() 
d.Add ("one",1) 
d.Add ("two",2) 
d.Add ("three",3) 

E il seguente codice di prova

let r1,v1 = d.TryGetValue "one" 
let r2,v2 = c.TryGetValue "one" 

R1, linea v1 funziona bene. Le bombe r2, v2 line; lamentando c.TryGetValue deve essere data una tupla. È interessante notare che in ogni riga la firma di TryGetValue è diversa. Come posso ottenere che la mia implementazione personalizzata mostri lo stesso comportamento della versione BCL? O, chiesto in un altro modo, poiché F # ha (implicitamente) il concetto di parametri di tupla, parametri curried e parametri BCL, e so come distinguere tra stile curried e tuple, come posso forzare il terzo stile (a metodi la BCL))?

Fammi sapere se questo non è chiaro.

risposta

8

TryGetValue ha un parametro out, quindi è necessario fare lo stesso in F # (tramite un byref contrassegnati con OutAttribute):

open System.Runtime.InteropServices 
type MyDict<'K,'V when 'K : equality>() = // ' 
    let d = new System.Collections.Generic.Dictionary<'K,'V>() 
    member this.TryGetValue(k : 'K, [<Out>] v: byref<'V>) = 
     let ok, r = d.TryGetValue(k) 
     if ok then 
      v <- r 
     ok    

let d = new MyDict<string,int>() 
let ok, i = d.TryGetValue("hi") 
let mutable j = 0 
let ok2 = d.TryGetValue("hi", &j) 

F # permette automagicamente si accende suffisso fuori parametri in valori di ritorno, quindi basta è necessario creare un metodo che termini in un parametro out.

+0

Grazie. In realtà l'ho provato, ma non avevo capito che avevo bisogno di OutAttribute. Ho pensato che il suffisso <'v> sarebbe stato sufficiente. – pblasucci

+0

byref di per sé è come 'ref' in C# (in contrapposizione a C# 'out'). – Brian

+2

ah, sì: ref, out ... dammi solo tuple ogni giorno! – pblasucci

4

Personalmente, non mi è mai piaciuto il pattern bool TryXXX(stringToParseOrKeyToLookup, out parsedInputOrLookupValue_DefaultIfParseFailsOrLookupNotFound) utilizzato in tutto il BCL. E mentre il trucco di F # di restituire una tupla è bello, raramente se mai ho effettivamente bisogno del valore predefinito se un parsing o una ricerca fallisce. In effetti, il modello Some/None sarebbe perfetto (come Seq.tryFind):

type MyClass() = 
    let items = System.Collections.Generic.Dictionary<string,int>() 
    do 
    items.Add ("one",1) 
    items.Add ("two",2) 
    items.Add ("three",3) 
    member this.TryGetValue (key) = 
    match items.TryGetValue(key) with 
     | (true, v) -> Some(v) 
     | _ -> None 

let c = MyClass() 

let printKeyValue key = 
    match c.TryGetValue(key) with 
    | Some(value) -> printfn "key=%s, value=%i" key value 
    | None -> printfn "key=%s, value=None" key 

//> printKeyValue "three";; 
//key=three, value=3 
//val it : unit =() 
//> printKeyValue "four";; 
//key=four, value=None 
//val it : unit =() 
+0

utilizzando 'match with' qui per abbinare la tupla è pura poesia. Ho usato questo approccio nel mio codice, molto bello! Grazie! – gjvdkamp

Problemi correlati