为什么通用ICollection在.NET 4.5中实现IReadOnlyCollection?
在.NET 4.5 / C#5中, IReadOnlyCollection<T>用Count属性声明: 
 public interface IReadOnlyCollection<out T> : IEnumerable<T>, IEnumerable { int Count { get; } } 
 我想知道,对于ICollection<T>实现IReadOnlyCollection<T>接口是否有意义: 
 public interface ICollection<T> : IEnumerable<T>, IEnumerable, *IReadOnlyCollection<T>* 
 这意味着实现ICollection<T>将自动实现IReadOnlyCollection<T> 。 这听起来对我来说很合理。 
  ICollection<T>抽象可以看作是IReadOnlyCollection<T>抽象的扩展。 请注意, List<T> ,例如,同时实现ICollection<T>和IReadOnlyCollection<T> 。 
然而它并没有被devise成这样。
我在这里错过了什么? 为什么会select当前的实施呢?
UPDATE
我正在寻找一个使用面向对象devise推理来解释原因的答案:
-  实现IReadOnlyCollection<T>和ICollection<T>具体类如List<T>ICollection<T>
是比以下更好的devise:
-   ICollection<T>IReadOnlyCollection<T>直接实现IReadOnlyCollection<T>
还请注意,这基本上是一样的问题:
-  为什么IList<T>实现IReadOnlyList<T>?
-  为什么不IDictionary<T>实现IReadOnlyDictionary<T>?
乔恩在这里https://stackoverflow.com/a/12622784/395144 ,你应该把他的答复标记为答案:
 int ICollection<Foo>.Count { ... } // compiler error! 
由于接口可以有明确的实现,所以提取基本接口不是向后兼容的(基类没有这个问题)。
这就是为什么…
 Collection<T> : IReadOnlyCollection<T> List<T> : IReadOnlyList<T> Dictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue> 
…但不是他们的接口。
恕我直言,他们做了一个devise错误最初,现在相当无法解决(没有打破东西)。
编辑:隐藏不帮助,旧的(显式的)实现将不会仍然生成(不修改代码):
 interface INew<out T> { T Get(); } interface IOld<T> : INew<T> { void Set(T value); new T Get(); } class Old<T> : IOld<T> { T IOld<T>.Get() { return default(T); } void IOld<T>.Set(T value) { } } 
'Sample.Old'不实现接口成员'Sample.INew.Get()'
可能有几个原因。 这里有两个顶部:
- 
巨大的向后兼容性问题 你将如何写 ICollection<T>的定义? 这看起来很自然:interface ICollection<T> : IReadOnlyCollection<T> { int Count { get; } }但它有一个问题,因为 IReadOnlyCollection<T>也声明了一个Count属性(编译器会在这里发出警告)。 除了这个警告之外,保持原样(相当于编写new int Count)允许实现者通过至less一个显式地实现两个Count属性的不同实现。 如果两个实现决定返回不同的值,这可能是“有趣的”。 允许人们用脚踢自己而不是C#的风格。好的,那么怎么样: interface ICollection<T> : IReadOnlyCollection<T> { // Count is "inherited" from IReadOnlyCollection<T> }那么,这将打破所有决定明确实现 Count现有代码:class UnluckyClass : ICollection<Foo> { int ICollection<Foo>.Count { ... } // compiler error! }因此,在我看来,这个问题没有好的解决scheme:要么破坏现有的代码,要么迫使每个人都容易出错。 所以唯一的胜利就是不玩 。 
- 
语义运行时types检查 编写像这样的代码将是没有意义的 if (collection is IReadOnlyCollection<Foo>)(或reflection的等价物),除非 IReadOnlyCollection<T>是“opt-in”:如果ICollection<T>是IReadOnlyCollection<Foo>的超集,那么太阳下的每个集合类都会通过这个testing,在实践中。
 这在语义上是错误的,因为显然不是每个ICollection都是只读的。 
 也就是说,他们可以调用接口IReadableCollection ,而一个实现可以被称为ReadOnlyCollection 。 
但是,他们没有走这条路。 为什么? 我看到一位BCL团队成员写道,他们不希望收集API变得过于复杂 。 (坦率地说,这已经是了。)
 当我第一次读到你的问题时,我想:“嘿,他是对的!那会最有意义的。” 但是界面的要点是描述一个合同 – 对行为的描述。 如果你的类实现了IReadOnlyCollection ,它应该是只读的。  Collection<T>不是。 所以对于一个Collection<T>来实现一个表示只读的接口可能会导致一些非常讨厌的问题。  IReadOnlyCollection消费者将会对这个底层集合做出某些假设 – 比如迭代它是安全的,因为没有人可以修改它等等。如果它的结构如你所说,可能不是真的! 
面向对象的devise推理来源于类和类实现的任何接口之间的“是”关系。
 在.NET 4.5 / c#5.0中, List<T>既是ICollection<T>又是IReadOnlyCollection<T> 。 您可以将List<T>实例化为任一types,具体取决于您希望如何使用集合。 
 当ICollection<T>实现IReadOnlyCollection<T> ,您可以让List<T>成为ICollection<T>或IReadOnlyCollection<T> ,这样做可以说ICollection<T> “是A” IReadOnlyCollection<T>它不是。 
更新
 如果从ICollection<T>inheritance的每个类实现了IReadOnlyCollection<T>那么我认为使ICollection<T>实现接口更有意义。 由于情况并非如此,请考虑如果ICollection<T>实现IReadOnlyCollection<T>会是什么样子: 
 public interface IReadOnlyCollection<T> : IEnumerable<T>, IEnumerable{}  
 public interface ICollection<T> : IReadOnlyCollection<T> {}
 如果您要查看ICollection<T>的签名,它看起来像是一个只读集合。 等等,让我们看看IReadOnlyCollection和ahh …它实现IEnumerable<T>和IEnumerable所以它不一定是只读集合。 在function上,原始问题提出的实现是相同的,但从语义上讲,我认为将接口实现尽可能推高是更正确的。 
这个接口更多的是一个描述接口,然后真正function的东西
在build议的方法中,每一个collections都必须被理解为你只能阅读广告的东西总是一样的。 所以你不能在创build之后添加或删除一个东西。
 我们可以问自己为什么这个接口被称为IReadOnlyCollection ,而不是'IReadOnlyEnumerable',因为它使用IEnumerable<T>, IEnumerable 。 答案很简单,这种types的接口不会有任何的困难,因为Enumerable已经是“只读”了。 
所以让我们看看文档IReadOnlyCollection(T)
描述中的第一个(也是最后一个)塞内加说:
表示一个强types的只读元素集合。
而且我认为这个解释了一切,如果你知道什么是强types的。
- 来自.Net 4.5的asynchronousHttpClient是密集加载应用程序的不好select吗?
- 无法首先将其转换为委托或expression式树types,不能将lambdaexpression式用作dynamic调度操作的参数
- 是否有可能在XP上运行.NET 4.5应用程序?
- 等待运营商只能在一个asynchronous方法内使用
- .NET中高级.NET 4.0和.NET 4.5之间的区别
- 从.Net 4.0到4.5的redirect解决scheme – 如何重新调整NuGet包?
- 为什么会find一个types的初始化器抛出一个NullReferenceException?
- HttpClient和HttpClientHandler必须被丢弃吗?
- 等待多个任务结果不同