Zai*_*sud 52 c# oop design-patterns c#-5.0 .net-4.5
在.NET 4.5/C#5中,IReadOnlyCollection<T>使用Count属性声明:
public interface IReadOnlyCollection<out T> : IEnumerable<T>, IEnumerable
{
int Count { get; }
}
Run Code Online (Sandbox Code Playgroud)
我想知道,ICollection<T>实现IReadOnlyCollection<T>接口也没有意义:
public interface ICollection<T> : IEnumerable<T>, IEnumerable, *IReadOnlyCollection<T>*
Run Code Online (Sandbox Code Playgroud)
这意味着实现的类ICollection<T>将自动实现IReadOnlyCollection<T>.这对我来说听起来很合理.
的ICollection<T>抽象可以被看作是所述的扩展IReadOnlyCollection<T>抽象.请注意List<T>,例如,实现两者ICollection<T>和IReadOnlyCollection<T>.
然而,它并没有这样设计.
我在这里错过了什么?为什么要选择当前的实现呢?
UPDATE
我正在寻找一个使用面向对象设计推理来解释原因的答案:
List<T>实现IReadOnlyCollection<T> 和 ICollection<T>是一个比以下更好的设计:
ICollection<T>IReadOnlyCollection<T>直接实施另请注意,这基本上与以下问题相同:
IList<T>实施IReadOnlyList<T>?IDictionary<T>实施IReadOnlyDictionary<T>?Jon*_*Jon 36
可能有几个原因.这里有两个顶部:
巨大的向后兼容性问题
你会如何写出定义ICollection<T>?这看起来很自然:
interface ICollection<T> : IReadOnlyCollection<T>
{
int Count { get; }
}
Run Code Online (Sandbox Code Playgroud)
但它有一个问题,因为IReadOnlyCollection<T>还声明了一个Count属性(编译器会在这里发出警告).除了警告之外,保持原样(相当于写入new int Count)允许实现者通过显式实现至少一个来实现两个属性的不同实现Count.如果两个实现决定返回不同的值,这可能是"有趣的".允许人们用脚射击自己不是C#的风格.
好的,那么呢:
interface ICollection<T> : IReadOnlyCollection<T>
{
// Count is "inherited" from IReadOnlyCollection<T>
}
Run Code Online (Sandbox Code Playgroud)
好吧,这会破坏所有决定Count明确实现的现有代码:
class UnluckyClass : ICollection<Foo>
{
int ICollection<Foo>.Count { ... } // compiler error!
}
Run Code Online (Sandbox Code Playgroud)
因此,在我看来,这个问题没有很好的解决方案:要么破坏现有代码,要么强制每个人都容易出错.所以唯一的胜利就是不打.
语义运行时类型检查
编写像代码一样没有意义
interface ICollection<T> : IReadOnlyCollection<T>
{
int Count { get; }
}
Run Code Online (Sandbox Code Playgroud)
(或等同于反思)除非ICollection<T>是"选择加入":如果IReadOnlyCollection<T>是一个超集,Count那么几乎所有太阳下的集合类都会通过这个测试,使其在实践中没用.
Not*_*sxl 14
乔恩就在这里/sf/answers/883594911/,你应该将他的答复标记为答案:
int ICollection<Foo>.Count { ... } // compiler error!
Run Code Online (Sandbox Code Playgroud)
由于接口可以具有显式实现,因此提取基接口不向后兼容(对于基类,您没有此问题).
这就是为什么...
Collection<T> : IReadOnlyCollection<T>
List<T> : IReadOnlyList<T>
Dictionary<TKey, TValue> : IReadOnlyDictionary<TKey, TValue>
Run Code Online (Sandbox Code Playgroud)
......但不是他们的界面.
恕我直言,他们最初做了一个设计错误,现在相当无法解决(没有破坏事情).
编辑:隐藏没有帮助,旧(显式)实现仍然不会构建(不修改代码):
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) { }
}
Run Code Online (Sandbox Code Playgroud)
'Sample.Old'没有实现接口成员'Sample.INew.Get()'