为什么Dictionary <TKey,TValue>没有IEnumerable <KeyValuePair <TKey,TValue >> ctor?

And*_*tan 14 .net generics

好的 - 所以我知道构建提供功能的工厂方法很简单; 但鉴于Dictionary<TKey, TValue>IEnumerable<KeyValuePair<TKey, TValue>>,不应该它有一个构造函数等同于,例如,List<T>ctor(IEnumerable<T> range)

它甚至更狡猾,因为它提供了一个IDictionary<TKey, TValue>作为源的Ctor ,但由于该接口也是IEnumerable<KeyValuePair<TKey, TValue>>,IEnumerable选项肯定会更有意义; 除非在IEnumerable<>课程首次设计时界面不在身边.

它变得更糟,因为如果你看一下ctor的IDictionary版本的实现 - 使用以下代码导入输入字典:

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

任何人都想到一个很好的理由,为什么框架设计者在基本界面需要的时候选择了最具体的界面?

编辑

@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);
}
Run Code Online (Sandbox Code Playgroud)

我知道 - 测试反过来 - 但出于某种原因我认为这让我的观点更好:)

鉴于Key comparer不是IDictionary接口的一部分,您永远不能保证您导入的字典不会生成重复的键,因此ArgumentException在构造新的键时也不会.

Ergo - 您可能只有一个IEnumerable构造函数可以执行相同的操作.

Mar*_*ann 13

完全非官方的猜测:

如果一个构造函数允许IEnumerable<KeyValuePair<TKey, TValue>>你可以提供具有相同键的多个项目,那么它的预期行为是什么?

你可以这样做:

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);
Run Code Online (Sandbox Code Playgroud)

您可以争辩说,这应该只是抛出一个异常以与Add方法的行为一致,但我猜想设计团队认为这将是一个更大的混乱来源而不是实际有用......

  • +1这是一个好点 - 可能非常接近真相.然而,如果那是设计决定,那么它是一个有缺陷的:我可以传入一个Dictionary <TKey,TValue>实例,它使用限制较少的IComparer(例如默认的StringComparer而不是不区分大小写的),而不是新的仍然可以生成异常.一个IDictionary不一定是另一个IDictionary make. (5认同)
  • 他们可能应该省略带有IDictionary*和*比较器的构造函数重载.负责此事的建筑师现在可能已被踢到楼上. - > (3认同)
  • 同样,我们可以看到`Dictionary'也'缺乏'一个`AddRange` - 也许是出于类似的原因? (2认同)