开发者

Why doesn't Dictionary<TKey, TValue> have an IEnumerable<KeyValuePair<TKey, TValue>> ctor?

Okay - so I know it's simple to build a factory method that provides the functionality; but given that Dictionary<TKey, TValue> is IEnumerable<KeyValuePair<TKey, TValue>>, shouldn't it have a Ctor equivalent to, for example, List<T>'s ctor(IEnumerable<T> range)?

It's even sillier given that it provides a Ctor that takes an IDictionary<TKey, TValue> as a source, but since that interface is also IEnumerable<KeyValuePair<TKey, TValue>>, the IEnumerable option would surely have made more sense; unless the IEnumerable<> interface wasn't around when the class first designed.

It get's worse because if you look at the implementation of the IDictionary version of the ctor - the input dictionary is imported with the following code:

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

Anyone think of a good reason for why the framework designers chose the most specific interface when a base interface was all that was required?

Edit

@Mark Seeman suggests that it's to avoid Exceptions being raised by duplicate keys - which is probably close to the truth - but consider this example:

[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);
}

I know - the test's in reverse - but for some reason I thought it made my point better :)

Given that the Key comparer is not part of the IDictionary interface, you can never guarantee that the dictionary you're importing will not generate duplicate keys, and therefore an ArgumentException, in constructing the new one.

Ergo - you might as well just have an IEnumerable construc开发者_运维百科tor that does the same thing.


Totally unofficial guess:

If a constructor allowed an IEnumerable<KeyValuePair<TKey, TValue>> you would have been able to supply multiple items with the same key and what would be the expected behavior of that?

E.g. you could have done something like this:

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);

You could argue that this should simply throw an exception to be consistent with the behavior of the Add method, but I would guess that the design team thought it would be a greater source of confusion than actually useful...


  public static Dictionary<T, U> ToDictionary(
      this IEnumerable<KeyValuePair<T, U>> source)
  {
    return source.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
  }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜