如何实现与Dictionary.TryGetValue相同的行为

时间:2010-04-27 22:03:02

标签: .net f# implementation byref out-parameters

所以,然后给出以下代码

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)

以下测试代码

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

r1,v1行正常工作。 r2,v2线炸弹;抱怨c.TryGetValue必须给出一个元组。有趣的是,在每行中,TryGetValue的签名是不同的。如何让我的自定义实现显示与BCL版本相同的行为?或者,问另一种方式,因为F#具有(隐式)元组参数,curried参数和BCL参数的概念,而且我知道如何区分curried和tuple-style,我怎么能强制第三种样式(a la BCL方法) )?

如果不清楚,请告诉我。

2 个答案:

答案 0 :(得分:8)

TryGetValue有一个out参数,因此您需要在F#中执行相同操作(通过标有byref的{​​{1}}):

OutAttribute

F#自动允许您将后缀输出参数转换为返回值,因此您只需要创建一个以out参数结尾的方法。

答案 1 :(得分:4)

就个人而言,我从未喜欢整个BCL使用的bool TryXXX(stringToParseOrKeyToLookup, out parsedInputOrLookupValue_DefaultIfParseFailsOrLookupNotFound)模式。虽然返回元组的F#技巧很好,但是如果解析或查找失败,我很少需要默认值。事实上,Some / None模式将是完美的(如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 = ()