gpt4 book ai didi

C#实现接口(interface)时的协变和逆变

转载 作者:太空狗 更新时间:2023-10-29 17:51:09 68 4
gpt4 key购买 nike

我最近决定复习一下 C# 基础知识,所以这可能是微不足道的,但我遇到了以下问题:

StringCollection 在 .NET v1.0 中用于为字符串创建强类型集合,而不是基于 ArrayList对象 (这后来通过包含通用集合得到增强):

快速浏览一下 StringCollection 定义,您可以看到以下内容:

// Summary:
// Represents a collection of strings.
[Serializable]
public class StringCollection : IList, ICollection, IEnumerable
{
...
public int Add(string value);
...
}

您可以看到它实现了 IList,其中包含以下声明(以及其他一些声明):

int Add(object value);

但不是:

int Add(string value);

我的第一个假设是,由于 .NET 框架协变规则,这是可能的。

所以为了确保,我尝试编写自己的类来实现 IList 并进行更改

int Add(object value);

检索字符串类型而不是对象类型,但令我惊讶的是,在尝试编译项目时,我遇到了编译时错误:

does not implement interface member 'System.Collections.IList.Add(object)'

知道是什么原因造成的吗?

谢谢!

最佳答案

该行为是由 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)
}
}

可以观察到这种区别:

  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

附录

以上内容并未说明实现此模式的原因。 C# 语言规范指出 [§13.4.1,已强调]:

In some cases, the name of an interface member may not be appropriate for the implementing class, in which case the interface member may be implemented using explicit interface member implementation. [...]

It is not possible to access an explicit interface member implementation through its fully qualified name in a method invocation, property access, or indexer access. An explicit interface member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name.

StringCollection 遵循所需的 IList 行为——IList 不保证可以向其中添加任何任意对象。 StringCollection 提供了更强的保证——主要是它只包含字符串。该类包括它自己的强类型方法,用于 AddContainsItem 以及其他用于标准用例的方法,其中它作为StringCollection 而不是 IList。但它仍然可以作为 IList 完美运行,接受和返回对象,但如果尝试添加不是字符串的项目,则返回错误代码(如 IList 允许的那样)。

最终,接口(interface)是否出现在类中(即显式实现)由类作者自行决定。对于框架类,显式实现包含在 MSDN 文档中,但不能作为类成员访问(例如,显示在自动完成上下文中)。

关于C#实现接口(interface)时的协变和逆变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7054497/

68 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com