.net 只读集合<;T>;实施IList<;T>;但是';t实现add方法

.net 只读集合<;T>;实施IList<;T>;但是';t实现add方法,.net,.net,System.Collections.ObjectModel.ReadOnlyCollection如何实现System.Collections.Generic.IList但不实现其Add方法 我不是问为什么它没有一个Add方法——这是显而易见的,因为它应该是只读的;我想问的是,它如何在不实现IList接口契约所要求的方法的情况下逃之夭夭。它显式地实现了该方法,以及其他几个通常会改变底层集合的方法。请参见下页的“显式接口实现”部分: Add方法的备注部分指出了他们使用显式实现的原因: 此成员是显

System.Collections.ObjectModel.ReadOnlyCollection
如何实现
System.Collections.Generic.IList
但不实现其
Add
方法


我不是问为什么它没有一个
Add
方法——这是显而易见的,因为它应该是只读的;我想问的是,它如何在不实现IList接口契约所要求的方法的情况下逃之夭夭。

它显式地实现了该方法,以及其他几个通常会改变底层集合的方法。请参见下页的“显式接口实现”部分:

Add
方法的备注部分指出了他们使用显式实现的原因:

此成员是显式接口成员实现。仅当将
ReadOnlyCollection
实例强制转换为
ICollection
接口时,才可以使用它

因此,开发人员无法直接在
ReadOnlyCollection
的实例上调用
Add
方法(这无论如何都没有意义)。当接口方法的实现由于附加在实现类上的约束(在本例中,对象是只读的)而总是引发异常时,经常使用显式接口实现

有关更多信息,请参阅第页


奖励用例:

我使用显式接口实现的另一个地方是接口方法的实现过于复杂,派生类型可能会在逻辑中引入错误。例如,考虑<代码> iOnMoMangdToal.QueSturys<代码>的复杂实现。本规范为所有锅炉板规范,仅用于正确行为。它实际上不提供任何命令的状态


查看
ReadOnlyCollection
实现,可以看到
Add
方法的实现如下:

int IList.Add(object value)
{
    ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
    return -1;
}
正如您所看到的,它实际上是一个of
IList.Add
方法。这解释了为什么
Add
方法不能直接从
ReadOnlyCollection
中获得。如果将该值强制转换为
IList
,则可以调用它,但这将始终导致引发
NotSupportedException

请注意,其他
IList
方法,如
Clear
Insert
Remove
也以类似的方式在该类中实现,以及
ICollection
的一些方法:它们被显式实现并抛出异常


从.NET 4.5开始,
System.Collections.Generic.IReadOnlyCollection
现在已经存在。虽然
ReadOnlyCollection
类实现了它,但它仍然继续实现
IList
,我想这可能是出于可追溯性的原因。不过,如果您正在使用4.5并考虑自己实现一个只读集合,我建议您不要实现
IList
,而是使用
IReadOnlyCollection
,它是这样实现的:

int IList.Add(object value)
{
    ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
    return -1;
}
它还记录在:

将项目添加到IList。此实现始终引发NotSupportedException


除非您试图调用
Add
,否则会出现一个编译器错误,表明该方法不存在。@roryap Yes,因为您可以看到它是作为私有方法显式实现的。这意味着,虽然可以将对象强制转换为
IList
对象,但可以调用强制转换结果的
Add
方法。只有它会抛出异常。@roryap我在回答中添加了更多细节,请看一看。有一件事我不能接受,那就是作为私有方法的显式实现。如果你试图调用一个类的私有方法,你会得到一个编译器错误,
''在这个上下文中是不可访问的,因为它是“private”
,但是在这个类中,我得到的是“add”不是“System.Collections.ObjectModel.ReadOnlyCollection”的成员,“@roryap”被授予,一开始你很难对它下定论,但在这种情况下,它确实是有意义的。我建议您阅读关于显式实现的文档。我在回答中提供了链接。@Julián Urbano——我放弃了你的编辑。在我看来,问题的标题应该是title case,而且我的问题也不能由你来添加内容。@roryap只是试图澄清该方法已经实现,所以它不会“不实现该方法就逃跑”;它只是不能公开访问。至于标题案例,我不同意,因为这是一个高度区分大小写的网站(见这里)。但是,嘿,今天是星期五,快发疯吧。@JuliánUrbano--但是这个方法似乎没有实现。我得到了编译器错误
'a'不是'b'的成员
,而如果我调用了一个已实现但只是私有的方法,我会得到编译器错误
'a'在此上下文中不可访问,因为它是“私有的”
。因为该方法不是
ReadOnlyCollection.Add
,而是
IList.Add
。如果您强制转换到
IList
,那么您可以调用它(抛出异常)@JuliánUrbano——我知道该方法是
IList.Add
,但是如果它不是由
ReadOnlyCollection
实现的,那么抛出异常的代码在哪里呢?正如我对@Crono的评论,我不知道如何实现,如果试图调用类上的私有方法,则会出现编译器错误,
''在此上下文中不可访问,因为它是“private”
,但在此类中,我得到的
'add'不是“System.Collections.ObjectModel.ReadOnlyCollection”的成员。
int IList.Add(object value)
{
    ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
    return -1;
}
int IList.Add(object value)
{
    ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
    return -1;
}