Хорошо - поэтому я знаю, что просто создать метод factory, который обеспечивает функциональность; но при условии, что Dictionary<TKey, TValue>
есть IEnumerable<KeyValuePair<TKey, TValue>>
, не должен ли он иметь эквивалент Ctor, например, List<T>
ctor(IEnumerable<T> range)
?
Это еще глупее, поскольку он предоставляет Ctor, который принимает IDictionary<TKey, TValue>
как источник, но поскольку этот интерфейс также IEnumerable<KeyValuePair<TKey, TValue>>
, опция IEnumerable, несомненно, имела бы больше смысла; если интерфейс IEnumerable<>
не был вокруг, когда первый класс был разработан.
Ухудшается, потому что если вы посмотрите на реализацию версии IDictionary ctor - входной словарь импортируется с помощью следующего кода:
foreach (KeyValuePair<TKey, TValue> pair in dictionary)
{
this.Add(pair.Key, pair.Value);
}
Кто-нибудь думает о хорошей причине, почему дизайнеры фреймворков выбрали наиболее специфический интерфейс, когда базовый интерфейс был всем, что требовалось?
Edit
@Mark Seeman предполагает, что он должен избегать исключений, возникающих дублирующимися ключами, что, вероятно, близко к истине, но рассмотрим этот пример:
[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);
}
Я знаю - тест в обратном порядке - но почему-то я думал, что это улучшило мою точку зрения:)
Учитывая, что компаратор ключей не является частью интерфейса IDictionary, вы никогда не сможете гарантировать, что словарь, который вы импортируете, не будет генерировать повторяющиеся ключи и, следовательно, ArgumentException
при построении нового.
Ergo - вы можете просто иметь конструктор IEnumerable, который делает то же самое.