当我在 ArrayList 关键字上按 f12 转到从 vs2008 生成的元数据时,我发现生成的类声明如下
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
我知道 IList 已经从 ICollection 和 IEnumerable 继承了,那么为什么 ArrayList 会冗余地从这些接口继承呢?
当我在 ArrayList 关键字上按 f12 转到从 vs2008 生成的元数据时,我发现生成的类声明如下
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
我知道 IList 已经从 ICollection 和 IEnumerable 继承了,那么为什么 ArrayList 会冗余地从这些接口继承呢?
好的,我已经做了一些研究。如果您创建以下层次结构:
public interface One
{
void DoIt();
}
public interface Two : One
{
void DoItMore();
}
public class Magic : Two
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
并编译它,然后在不同的解决方案中引用 DLL,键入 Magic 并按 F12,您将得到以下信息:
public class Magic : Two, One
{
public Magic();
public void DoIt();
public void DoItMore();
}
您会看到接口层次结构是扁平化的,还是编译器正在添加接口?如果您使用反射器,您也会得到相同的结果。
更新:如果你在 ILDASM 中打开 DLL,你会看到它说:
实现...两个
实现...一个。
显示额外的接口是因为它们被 IList 隐含。如果实现 IList,则还必须实现 ICollection 和 IEnumerable。
我只是猜测,但我认为实际上它只在代码中实现 IList,但文档还显示了其余接口,以便使用该类的程序员明确说明。
来自MSDN ....
如果一个类实现了两个包含具有相同签名的成员的接口,那么在该类上实现该成员将导致两个接口都使用该成员作为它们的实现。
显式实现也用于解决两个接口各自声明具有相同名称的不同成员(例如属性和方法)的情况:
不要接受这个作为答案。
我在重复上面 workmad3 所说的话。
通过在 ArrayList 中实现它,人们很容易知道 - ArrayList 实现了哪些接口,而不是通过 IList 发现它实现了 ICollection 和 IEnumerable。
这避免了来回继承链的需要。
编辑:在基本级别,实现另一个接口的接口不能提供实现。派生的类(来自 IList)因此也间接实现了 ICollection 和 IEnumerable。因此,即使您编写自己的实现 IList 的类(而不是在声明中添加 ICollection、IEnumerable) - 您也会看到它必须提供 ICollection 和 IEnumerable 的实现。
workmad3 的推理是有道理的。
我的猜测是 CLR 不支持从另一个接口继承的接口。
然而,C# 确实支持这种构造,但必须“扁平化”继承树以符合 CLR。
[编辑]
从下面得到建议后,快速设置一个 VB.Net 项目:
Public Interface IOne
Sub DoIt()
End Interface
Public Interface ITwo
Inherits IOne
Sub DoIt2()
End Interface
Public Class Class1
Implements ITwo
Public Sub DoIt() Implements IOne.DoIt
Throw New NotImplementedException()
End Sub
Public Sub DoIt2() Implements ITwo.DoIt2
Throw New NotImplementedException()
End Sub
End Class
编译结果如下(C#):
public class Class1 : ITwo
{
public Class1();
public void DoIt();
public void DoIt2();
}
这表明与 C# 相比,VB.Net 不会扁平化接口层次结构。我不知道为什么会这样。