2010-04-27 35 views
7

Vì vậy, được đưa ra sau đó mã sauLàm thế nào tôi có thể thực hiện hành vi tương tự như 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) 

Và mã kiểm tra sau

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

Các r1, dòng v1 hoạt động tốt. Các dòng bom r2, v2; phàn nàn c.TryGetValue phải được đưa ra một tuple. Thật thú vị, trong mỗi dòng chữ ký của TryGetValue là khác nhau. Làm thế nào tôi có thể thực hiện tùy chỉnh của mình để thể hiện hành vi tương tự như phiên bản BCL? Hoặc, hỏi một cách khác, vì F # có (ngầm định) khái niệm tham số tuple, tham số curried, và tham số BCL, và tôi biết cách phân biệt giữa kiểu curried và tuple, làm thế nào tôi có thể ép kiểu thứ ba (a la BCL method)?

Hãy cho tôi biết nếu điều này không rõ ràng.

Trả lời

8

TryGetValue có một tham số ra, vì vậy bạn cần phải làm như vậy trong F # (thông qua một byref được đánh dấu bằng 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 # automagically cho phép bạn biến hậu tố ra thông số vào giá trị trả lại, vì vậy bạn chỉ cần phải tạo một phương thức kết thúc bằng tham số ngoài.

+0

Cảm ơn. Tôi thực sự đã thử điều đó, nhưng không nhận ra tôi cần OutAttribute. Tôi giả định byref <'v> sẽ là đủ. – pblasucci

+0

byref tự nó giống như 'ref' trong C# (trái với C# 'out'). – Brian

+2

ah, vâng: ref, out ... cứ cho tôi một tuples bất cứ ngày nào! – pblasucci

4

Cá nhân, tôi chưa bao giờ thích mẫu bool TryXXX(stringToParseOrKeyToLookup, out parsedInputOrLookupValue_DefaultIfParseFailsOrLookupNotFound) được sử dụng trong toàn BCL. Và trong khi F # lừa trả lại một tuple là tốt đẹp, hiếm khi nếu bao giờ tôi thực sự cần giá trị mặc định nếu một phân tích cú pháp hoặc tra cứu không thành công. Thật vậy, mẫu Some/None sẽ hoàn hảo (như 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

sử dụng 'khớp với' ở đây để phù hợp với tuple là thơ thuần khiết. Sử dụng cách tiếp cận này trong mã của tôi, rất đẹp! Cảm ơn! – gjvdkamp

Các vấn đề liên quan