拥有此代码......
var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 });
b[2] = 3;
我在第二行遇到编译错误。我期望发生运行时错误,因为ReadOnlyCollection<T>
实现了IList<T>
,而this[T]
在IList<T>
接口中有一个setter。
我试图复制ReadOnlyCollection的功能,但是从this[T]
删除setter是一个编译错误。
答案 0 :(得分:16)
indexer是通过显式接口实现实现的,因此如果您这样做,您将只能访问它:
IList<int> b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 });
b[2] = 3;
或
var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 });
((IList<int>)b)[2] = 3;
当然,它会在执行时失败......
这是完全有意识和有帮助的 - 这意味着当编译器知道它是ReadOnlyCollection
时,您无法使用不受支持的功能,从而帮助您远离执行时间失败。
这是一个有趣且相对不寻常的步骤,有效地隐式地实现了属性/索引器的一半,并且明确地实现了一半。
与我之前的想法相反,我认为ReadOnlyCollection<T>
实际明确地实现了整个索引器,但还提供了一个公共只读索引器。换句话说,它是这样的:
T IList<T>.this[int index]
{
// Delegate interface implementation to "normal" implementation
get { return this[index]; }
set { throw new NotSupportedException("Collection is read-only."); }
}
public T this[int index]
{
get { return ...; }
}
答案 1 :(得分:2)
它显式地实现了IList.Items,这使得它非公开,你必须强制转换到接口以实现它的实现,并实现一个新的this [...]索引器,它被用来代替,只有一个get-accessor。
如果将集合强制转换为IList,则代码将编译,但在运行时将失败。
不幸的是我不知道如何在C#中执行此操作,因为在C#中编写索引器涉及使用this
关键字,并且您不能这样写:
T IList<T>.this[int index] { get; set; }
答案 2 :(得分:1)
没有魔力,ReadOnlyCollection
只有不同的实现,它自己的索引器和实现IList<T>
接口的索引器:
public T Item[int index] { get; }
T IList<T>.Item[int index] { get; set; }
如果将列表转换为IList<int>
,则会出现运行时错误而不是编译错误:
((IList<int>)b)[2] = 3;
编辑:
要在您自己的类中实现索引器,请使用this
关键字:
public T this[int index] { get { ... } }
T IList<T>.this[int index] { get { ... } set { ... } }