标题说全部
为什么要String实施IEnumerable<char>而不是IList<char>?
字符串具有长度,您可以从特定索引中获取元素.
并且可以表明它是不可改变的ICollection<char>.IsReadOnly.
那么它可能有什么问题呢?我错过了什么吗?
正如许多答案所指出的那样:
没有单独的只读列表/集合的界面,但是作为ReadOnlyCollection<T>节目,我认为它绝对可能并且使用它IsReadOnly为这种情况设计的属性.
public class String : IList<char>
{
int IList<char>.IndexOf(char item)
{
// ...
}
void IList<char>.Insert(int index, char item)
{
throw new NotSupportedException();
}
void IList<char>.RemoveAt(int index)
{
throw new NotSupportedException();
}
char IList<char>.this[int index]
{
set
{
throw new NotSupportedException();
}
}
void ICollection<char>.Add(char item)
{
throw new NotSupportedException();
}
void ICollection<char>.Clear()
{
throw new NotSupportedException();
}
public bool Contains(char item)
{
// ...
}
public void CopyTo(char[] array, int arrayIndex)
{
// ...
}
int ICollection<char>.Count
{
get { return this.Length; }
}
public bool IsReadOnly
{
get { return true; }
}
bool ICollection<char>.Remove(char item)
{
throw new NotSupportedException();
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
Jef*_*nal 14
主要是因为IList继承自ICollection,而字符串不支持可变的beahviors ICollectionpromises(添加,删除和清除) - 当您从字符串添加或删除字符元素时,它会创建一个新字符串.
实现接口的一部分是糟糕的设计.你有时可能会出于必要而做,但这绝不是一个好的选择.分割界面更好.(可能已经拆分了.NET集合接口以将可变成员与诊断成员隔离开来.)元函数IsReadOnly使得界面不那么连贯并使其更难使用.
所以即使一个字符串在很多方面都是一个列表 - 你可以索引一个字符串并找到其中的字符数 - 很少有人真正想要像对待一个字符串IList<char>,特别是在3.5后的世界中当有简单的转换时,可以很容易地从中获取此信息IEnumerable<char>.
我认为高度ReadOnlyCollection支持的事实是: meh。IList
IList是一个契约,表明实现者支持集合突变(例如添加、删除、插入),这在不可变对象上显然是错误的。将其转移到System.String是完全错误的,因为它在设计上也是不可变的。
System.String实现IList将是一个糟糕的 API 设计,因为一堆方法将不起作用,因此字符串不会以与完全实现的类型相同的方式工作IList。
也许您希望它支持更自由的界面,当然,但这IList不是正确的选择。
像这样的部分接口实现打破了里氏替换原则,并引入了潜在的运行时错误。
更新
有趣的是,.Net 4.5 引入了新的IReadOnlyList接口。但是,String没有实现它,并且无法将其引入IList层次结构中。
一些背景:http://www.infoq.com/news/2011/10/ReadOnly-WInRT。
主要是,它不是一个 IList(你不能"hello world".Add('!')——这是一个接口和契约不兼容;它不仅仅是一个只读列表,因为它会“知道”该Add操作,并在调用时抛出)。
此外,字符串具有特殊的语义 - 存储优化和身份别名(可以有小字符串优化,可以有内部字符串)。一旦您传递为,这些就不会脱颖而出IList<char>- 人们可能会开始期待“正常”的类似 List<> 的语义。
然而,当看到 时IEnumerable<char>,并没有提出这样的期望(它只是说:我可以连续给你一些角色,你不需要知道他们来自哪里)。