Mik*_* S. 9 .net c# inheritance interface covariance
我最近决定刷新我对C#基础知识的记忆,所以这可能是微不足道的,但我遇到了以下问题:
StringCollection在.NET v1.0中使用,以便为字符串创建强类型集合而不是object基于字符串ArrayList(后来通过包含泛型集合来增强):
快速浏览一下StringCollection定义,您可以看到以下内容:
// Summary:
// Represents a collection of strings.
[Serializable]
public class StringCollection : IList, ICollection, IEnumerable
{
...
public int Add(string value);
...
}
Run Code Online (Sandbox Code Playgroud)
你可以看到它实现IList,它包含以下声明(在其他一些声明中):
int Add(object value);
Run Code Online (Sandbox Code Playgroud)
但不是:
int Add(string value);
Run Code Online (Sandbox Code Playgroud)
我的第一个假设是,由于.NET框架协方差规则,它是可能的.
所以,为了确保,我尝试编写自己的实现IList和更改的类
int Add(object value);
Run Code Online (Sandbox Code Playgroud)
检索字符串类型而不是对象类型,但令我惊讶的是,在尝试编译项目时,我遇到了编译时错误:
does not implement interface member 'System.Collections.IList.Add(object)'
Run Code Online (Sandbox Code Playgroud)
有什么想法导致这个?
谢谢!
这种行为是由明确的实施IList.Add(object)而非共同/逆转引起的.根据MSDN文档,StringCollection显式实现IList.Add(object); 这种Add(string)方法是无关的.实现可能类似于以下内容:
class StringCollection : IList
{
...
public int Add(string value)
{} // implementation
public int IList.Add (object value)
{
if (!value is string)) return -1;
return Add(value as string)
}
}
Run Code Online (Sandbox Code Playgroud)
可以观察到这种区别:
StringCollection collection = new StringCollection();
collection.Add(1); // compile error
(collection as IList).Add(1); // compiles, runtime error
(collection as IList).Add((object)"") // calls interface method, which adds string to collection
Run Code Online (Sandbox Code Playgroud)
附录
以上并未解释为何实现此模式.C#语言规范指出[§13.4.1,强调增加]:
在某些情况下,接口成员的名称可能不适合实现类,在这种情况下,接口成员可以使用显式接口成员实现来实现.[...]
在方法调用,属性访问或索引器访问中,无法通过其完全限定名称访问显式接口成员实现.显式接口成员实现只能通过接口实例访问,并且在这种情况下仅通过其成员名称引用.
StringCollection遵循所需的IList行为--Ilist不保证可以向其添加任何任意对象.StringCollection提供更强的保证 - 主要是它只包含字符串.类包括它自己的强类型的方法Add,Contains,Item,和其他人在那里作为访问的标准使用情况StringCollection,而不是一个IList.但它仍然可以很好地作为IList接受和返回对象,但如果尝试添加不是字符串的项,则返回错误代码(如IList允许).
最终,类接口是否显示在类中(即明确实现)由类作者自行决定.对于框架类,显式实现包含在MSDN文档中,但不能作为类成员访问(例如,在自动完成上下文中显示).