2010-02-12 37 views
14

Được rồi - vì vậy tôi biết thật đơn giản để xây dựng một phương pháp nhà máy cung cấp chức năng; nhưng cho rằng Dictionary<TKey, TValue>IEnumerable<KeyValuePair<TKey, TValue>>, không nên có Ctor tương đương, ví dụ: List<T> 's ctor(IEnumerable<T> range)?Tại sao từ điển <TKey, TValue> không có một trình duyệt <KeyValuePair <TKey, TValue >>?

Nó thậm chí còn sillier cho rằng nó cung cấp một Ctor mất IDictionary<TKey, TValue> như một nguồn, nhưng vì giao diện đó cũng là IEnumerable<KeyValuePair<TKey, TValue>>, tùy chọn IEnumerable chắc chắn sẽ có ý nghĩa hơn; trừ khi giao diện IEnumerable<> không xung quanh khi lớp được thiết kế lần đầu tiên.

Nó được tồi tệ hơn bởi vì nếu bạn nhìn vào việc thực hiện của phiên bản IDictionary của ctor - từ điển đầu vào được nhập khẩu với đoạn mã sau:

foreach (KeyValuePair<TKey, TValue> pair in dictionary) 
{ 
    this.Add(pair.Key, pair.Value); 
} 

Bất cứ ai cũng nghĩ đến một lý do chính đáng cho lý do tại sao các nhà thiết kế khung chọn giao diện cụ thể nhất khi giao diện cơ sở là tất cả những gì được yêu cầu?

Sửa

@ Mark Seeman gợi ý rằng đó là để tránh trường hợp ngoại lệ được nêu ra bởi các phím trùng lặp - mà có lẽ gần với sự thật - nhưng xem xét ví dụ sau:

[TestMethod] 
[ExpectedException(typeof(ArgumentException))] 
public void How_To_Break_The_IDictionary_Ctor_Design_Decision() 
{ 
    Dictionary<string, string> dictionary = new Dictionary<string, string>(); 
    dictionary.Add("hello", "world"); 
    dictionary.Add("Hello", "world"); 

    Dictionary<string, string> dictionary2 = 
    new Dictionary<string, string>(dictionary, 
            StringComparer.CurrentCultureIgnoreCase); 
} 

tôi biết - kiểm tra ngược lại - nhưng vì một lý do nào đó tôi nghĩ nó làm cho điểm của tôi tốt hơn :)

Cho rằng bộ so sánh chính không phải là một phần của IDiction giao diện ary, bạn có thể không bao giờ đảm bảo rằng từ điển bạn đang nhập sẽ không tạo các khóa trùng lặp và do đó, hãy tạo ArgumentException, trong khi tạo từ khóa mới.

Ergo - bạn cũng có thể có một hàm tạo IEnumerable thực hiện tương tự.

+0

Tôi đã yêu cầu điều tương tự cho Guava gần đây: http://code.google.com/p/guava-libraries/issues/detail?id=320 – finnw

Trả lời

13

Hoàn toàn không chính thức đoán:

Nếu một constructor cho phép một IEnumerable<KeyValuePair<TKey, TValue>> bạn sẽ có được khả năng cung cấp nhiều mặt hàng có cùng quan trọng và những gì sẽ là hành vi dự kiến ​​về điều đó?

Ví dụ: bạn có thể làm điều gì đó như thế này:

var kvps = new[] 
{ 
    new KeyValuePair<int, string>(1, "Foo"), 
    new KeyValuePair<int, string>(1, "Bar"), 
    new KeyValuePair<int, string>(1, "Baz")   
} 
var dic = new Dictionary<int, string>(kvps); 

Bạn có thể chỉ cần ném một ngoại lệ để phù hợp với hành vi của phương pháp Thêm, nhưng tôi đoán nhóm thiết kế nghĩ rằng nó sẽ lớn hơn nguồn gây nhầm lẫn hơn thực sự hữu ích ...

+2

trong cùng một mạch, chúng ta có thể thấy rằng 'Từ điển' cũng 'thiếu' một' AddRange' - vì một lý do tương tự có lẽ? – AakashM

+1

Trong khi điều này có thể không phải là lý do chính thức, nó đủ tốt để biện minh cho sự vắng mặt của kiến ​​trúc 'IEnumerable >'. –

+5

+1 Đó là một điểm tốt - và có lẽ khá gần với sự thật. Tuy nhiên, nếu đó là quyết định thiết kế thì đó là một quyết định sai lầm: tôi có thể chuyển sang một phiên bản từ điển sử dụng IComparer ít hạn chế hơn (ví dụ:mặc định StringComparer so với trường hợp không phân biệt dạng chữ) so với cái mới mà vẫn có thể tạo ra một ngoại lệ. Một IDictionary không nhất thiết phải tạo ra một IDictionary khác. –

1
public static Dictionary<T, U> ToDictionary(
     this IEnumerable<KeyValuePair<T, U>> source) 
    { 
    return source.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); 
    } 
Các vấn đề liên quan