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);
}
精彩评论