C# 为什么';在.NET 4.5中,通用ICollection是否实现DirectAdonlyCollection?
在.NET 4.5/C#5中,C# 为什么';在.NET 4.5中,通用ICollection是否实现DirectAdonlyCollection?,c#,oop,design-patterns,.net-4.5,c#-5.0,C#,Oop,Design Patterns,.net 4.5,C# 5.0,在.NET 4.5/C#5中,IReadOnlyCollection使用Count属性声明: public interface IReadOnlyCollection<out T> : IEnumerable<T>, IEnumerable { int Count { get; } } 公共接口IReadOnlyCollection:IEnumerable,IEnumerable { 整数计数{get;} } 我想知道,ICollection是否也可以实现IR
IReadOnlyCollection
使用Count
属性声明:
public interface IReadOnlyCollection<out T> : IEnumerable<T>, IEnumerable
{
int Count { get; }
}
公共接口IReadOnlyCollection:IEnumerable,IEnumerable
{
整数计数{get;}
}
我想知道,ICollection
是否也可以实现IReadOnlyCollection
接口:
public interface ICollection<T> : IEnumerable<T>, IEnumerable, *IReadOnlyCollection<T>*
公共接口ICollection:IEnumerable,IEnumerable,*IReadOnlyCollection*
这意味着实现ICollection
的类将自动实现IReadOnlyCollection
。这听起来很合理
ICollection
抽象可以看作是IReadOnlyCollection
抽象的扩展。请注意,例如,List
实现了ICollection
和IReadOnlyCollection
然而,它并不是这样设计的
我错过了什么?为什么会选择当前的实现
更新 我正在寻找一个使用面向对象设计推理来解释原因的答案:
- 一个具体的类,如
实现了List
和IReadOnlyCollection
ICollection
直接实施i收集
IReadOnlyCollection
还请注意,这与以下问题基本相同:
IDictionary
不实现IReadOnlyDictionary
当我第一次读到你的问题时,我想“嘿,他是对的!那将是最有意义的。”但是界面的重点是描述一个合同——一个行为的描述。如果类实现了
IReadOnlyCollection
,则它应该是只读的<代码>集合不是。因此,对于集合
来说,实现一个隐含只读的接口可能会导致一些非常严重的问题。IReadOnlyCollection
的消费者将对该基础集合做出某些假设,比如在它上面进行迭代是安全的,因为没有人可以修改它,等等。如果它是按照您建议的结构构建的,那么这可能不是真的 可能有几个原因。以下是一些:
- 巨大的向后兼容性问题
您将如何编写
的定义?这看起来很自然:i收集
好的,这将打破所有决定显式实现interface ICollection<T> : IReadOnlyCollection<T> { int Count { get; } }
的现有代码:Count
class UnluckyClass : ICollection<Foo> { int ICollection<Foo>.Count { ... } // compiler error! }
因此,在我看来,这个问题没有好的解决方案:要么破坏现有的代码,要么对每个人强制执行容易出错的实现。所以class解锁class:ICollection { int ICollection.Count{…}//编译器错误! }
- 这在语义上是错误的,因为显然,不是每个
i集合都是只读的
也就是说,他们可以调用接口IReadableCollection
,而实现可以调用ReadOnlyCollection
然而,他们没有走那条路。为什么?我看到了一个。(坦率地说,尽管它已经是了。)这个接口更多的是一个描述接口,而不是真正的功能性接口
在建议的方法中,每一个收藏都必须被理解为你只能阅读的东西,因为广告总是一样的。因此,您无法在创建后添加或删除对象
我们可以问问自己,为什么该接口被称为IReadOnlyCollection
,而不是使用IEnumerable,IEnumerable
的“ireadonlynumerable”。答案很简单,这种类型的接口没有任何意义,因为Enumerable已经是“只读的”
那么让我们看看医生
描述中的第一个(也是最后一个)意思是:
表示元素的强类型只读集合
我认为这可以解释一切,如果你知道它的用途的话。面向对象的设计推理将源于类和类实现的任何接口之间的“是一个”关系
在.NET 4.5/c中,5.0List
既是i集合
又是IReadOnlyCollection
。您可以将列表
实例化为任意一种类型,具体取决于您希望集合的使用方式
当使用ICollection
实现IReadOnlyCollection
时,您可以将List
设置为ICollection
或IReadOnlyCollection
,这样做就意味着ICollection
“是一个”IReadOnlyCollection
,而不是
已更新
如果从ICollection
继承的每个类都实现了IReadOnlyCollection
,那么我认为让ICollection
实现接口更有意义。由于情况并非如此,请考虑如果ICollection
要实现IReadOnlyCollection
,将会是什么样子:
公共接口IReadOnlyCollection:IEnumerable,IEnumerable{}
公共接口ICollection:IReadOnlyCollection{}
如果要查看ICollection
的签名,它看起来像是一个只读集合。等等,让我们看看IReadOnlyCollection和啊…它实现了IEnumerable
和IEnumerable
,所以它不一定是只读集合。从功能上讲,原始问题提出的实现是相同的,但从语义上讲,我认为将接口实现推到尽可能高的位置更为正确。Jon就在这里,您应该将他的回答标记为
class UnluckyClass : ICollection<Foo>
{
int ICollection<Foo>.Count { ... } // compiler error!
}
int ICollection<Foo>.Count { ... } // compiler error!
Collection<T> : IReadOnlyCollection<T>
List<T> : IReadOnlyList<T>
Dictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
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) { }
}