我正在查看C#集合初始化程序,发现实现非常务实,但也与C#中的任何其他内容完全不同
我能够创建这样的代码:
using System; using System.Collections; class Program { static void Main() { Test test = new Test { 1, 2, 3 }; } } class Test : IEnumerable { public IEnumerator GetEnumerator() { throw new NotImplementedException(); } public void Add(int i) { } }
由于我满足了编译器(已实现IEnumerable
和a public void Add
)的最低要求,因此无效,但显然没有价值.
我想知道是什么阻止了C#团队创建更严格的要求?换句话说,为了编译这种语法,为什么编译器不要求类型实现ICollection
?这似乎更符合其他C#功能的精神.
你的观察结果很明显 - 事实上,它反映的是由微软C#语言PM的Mads Torgersen制作的.
Mads于2006年10月就这个名为" 什么是收藏品"的主题发表了一篇文章?他写道:
承认,我们在System.Collections.ICollection的框架的第一个版本中吹了它,它旁边是无用的.但是当.NET Framework 2.0中出现泛型时我们很好地修复了它:System.Collections.Generic.ICollection
允许你添加和删除元素,枚举它们,计算它们并检查成员资格. 从那时起,每个人都会在每次收集时都实现ICollection
,对吧?不是这样.以下是我们如何使用LINQ来了解集合的真正含义,以及如何使我们在C#3.0中更改我们的语言设计.
事实证明,ICollection
框架中只有14个实现,但实现IEnumerable
并拥有公共Add()
方法的189个类.
这种方法有一个隐藏的好处 - 如果它们基于ICollection
接口,那么就会有一种支持的Add()
方法.
相反,他们采取的方法意味着集合的初始化器只是形成Add()
方法的参数集.
为了说明,让我们稍微扩展您的代码:
class Test : IEnumerable { public IEnumerator GetEnumerator() { throw new NotImplementedException(); } public void Add(int i) { } public void Add(int i, string s) { } }
你现在可以这样写:
class Program { static void Main() { Test test = new Test { 1, { 2, "two" }, 3 }; } }
我也考虑过这个问题,最让我满意的答案是ICollection除Add之外还有很多方法,例如:Clear,Contains,CopyTo和Remove.删除元素或清除与能够支持对象初始化程序语法无关,您只需要一个Add().
如果框架的设计足够精细,并且有一个ICollectionAdd接口,那么它将具有"完美"的设计.但老实说,我不认为这会增加很多价值,每个界面都有一个方法.IEnumerable + Add似乎是一种hackish方法,但是当你想到它时,它是一个更好的选择.
编辑:这不是C#解决此类解决方案问题的唯一时间.从.NET 1.1开始,foreach使用duck类型来枚举集合,所有类需要实现的是GetEnumerator,MoveNext和Current.Kirill Osenkov也有一个帖子,询问你的问题.