2012-06-20 29 views
8

Tôi đã hơi ngạc nhiên khi tôi nhận ra rằng F # 'map thực hiện cả hai IDictionary <' Key, 'Value> và ICollection<KeyValuePair<'a, 'b>> xem xét cả hai hỗ trợ đột biến (thêm và loại bỏ) như là một phần của hợp đồng.Tại sao F # map thực hiện các giao diện với các hoạt động có thể thay đổi?

Nhìn vào việc thực hiện map nó chỉ đơn giản là excepts khi bạn cố gắng gây ra đột biến!

let map = [| (1, "one"); (2, "two") |] |> Map.ofArray 
let dict = map :> IDictionary<int, string> 
dict.Add(3, "three");; 

mã ở trên ném ngoại lệ:

System.NotSupportedException: giá trị Bản đồ không thể bị đột biến. tại Microsoft.FSharp.Collections.FSharpMap 2.System-Collections-Generic-IDictionary 2 Thêm (TKey k, TValue v) tại. $ FSI_0007.main @() Ngưng do lỗi

đó là như mong đợi.

Đối với bộ sưu tập không thể thay đổi để có thể vạch trần chính nó như một bộ phận có thể thay đổi chỉ để loại trừ ngoại lệ khi người tiêu dùng bộ sưu tập đó gây ra đột biến có vẻ như là một quyết định nguy hiểm.

Tôi có thiếu gì đó ở đây không?

+2

Hàm ['dict'] (http://msdn.microsoft.com/en-us/library/ee353774.aspx) là một ví dụ khác. Nó trả về một _read only_ 'IDictionary <_,_>'. – Daniel

Trả lời

6

IsReadOnly cho phép giao diện được đọc chỉ mặc dù nó cung cấp phương thức ghi.

+0

điểm tốt, mặc dù nó rơi vào người tiêu dùng để luôn kiểm tra giá trị của tài sản đó nhưng tôi cho rằng đó là đủ công bằng – theburningmonk

4

Đó là một điều .Net. Bạn không thể thực hiện chỉ một số giao diện, nhưng họ muốn thực hiện giao diện IDictionary`2 - bởi vì bạn có thể sử dụng các phương thức truy vấn và chuyển đổi của nó (để bạn có thể chuyển nó tới các hàm đọc từ IDictionary`2).

9

Tôi nghĩ lý do chính là .NET không có bất kỳ giao diện nào đại diện cho bất biến (một phần của giao diện của từ điển). Điều này có nghĩa là tất cả các API .NET phải lấy tham số IDictionary<K, V>, ngay cả khi chúng chỉ có ý định đọc từ điển. Vì vậy:

  • Thực hiện IDictionary<'K, 'V> là khá nhiều cách duy nhất để làm cho F # bản đồ bất biến có thể sử dụng như một tham số để bất kỳ thư viện .NET cần một đối tượng có hỗ trợ tra cứu. Đáng buồn thay, không có thay thế chỉ đọc trong .NET.

  • Triển khai ICollection<KeyValuePair<'K, 'V>> không có nhiều ý nghĩa đối với tôi, bởi vì có một thay thế chỉ đọc IEnumerable<KeyValuePair<'K, 'V>> và bản đồ bất biến cũng thực hiện giao diện này.

    Nhưng có lẽ có một số thư viện .NET mất ICollection<'T> (để có hiệu quả - tức là để có được Count mà không liệt kê tất cả các phần tử) và sử dụng nó theo cách chỉ đọc.

    EDIT: Như chú thích của Daniel trong nhận xét, cần thực hiện ICollection vì giao diện IDictionary được thừa hưởng từ đó.

Tôi nghĩ rằng thiếu giao diện chỉ đọc khá đáng tiếc, nhưng có lẽ không có cách nào có thể sửa được, vì nó có nghĩa là thay đổi các thư viện thu thập .NET hiện có.

+3

'Bản đồ' phải triển khai 'ICollection >' vì ['IDictionary <_,_>'] (http://msdn.microsoft.com/en-us/library/s4ys34ea.aspx) thừa hưởng nó. – Daniel

+0

@Daniel Điểm tuyệt vời - cảm ơn! Tôi sẽ chỉnh sửa câu trả lời. –

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