当我按下f12键进入由vs2008生成的元数据时,我发现生成的类声明如下所示:
public class ArrayList : IList, ICollection, IEnumerable, ICloneable
我知道IList已经继承了ICollection和IEnumerable,那么为什么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文件,你会看到它说:
implements ...Two
implements ...One。
额外的接口显示出来是因为它们被IList暗示了。如果你实现了IList,那么你也必须实现ICollection和IEnumerable。
来自MSDN....
如果一个类实现了两个包含相同签名成员的接口,那么在该类上实现该成员将导致两个接口使用该成员作为它们的实现。
显式实现也用于解决两个接口声明同名成员(如属性和方法)的情况:
ArrayList 应该明确包含 ICollection 和 IEnumerable 实现,就像 IList 接口一样,它包含 ICollection 和 IEnumerable 实现。但 ArrayList 实现不应依赖于 IList。这样,如果列表结构发生变化,ArrayList 的行为不会受到影响。因此,它们必须被视为完全独立的。
继承 ICollection 和 IEnumerable 对于确保 ArrayList 的独立性非常重要。因此,如果 IList 结构发生更改并且未运行 ICollection 或 IEnumerable,则 ArrayList 结构将不会更改。
例如:
如果您创建以下层次结构:
public interface IOne
{
void DoIt();
}
public interface ITwo : IOne
{
void DoItMore();
}
public class Magic : ITwo
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
现在,接口 ITwo 决定不使用 IOne 实现。由于我们在 Magic 的实现中明确继承了 IOne,程序可以独立运行,不依赖于对 ITwo 接口的更改。
public interface IOne
{
void DoIt();
}
public interface ITwo
{
void DoItMore();
}
public class Magic : ITwo,IOne
{
public void DoItMore()
{
throw new NotImplementedException();
}
public void DoIt()
{
throw new NotImplementedException();
}
}
我的猜测是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并不会扁平化接口层次结构。我不知道为什么会这样。
不要接受这个作为答案。
我在重复workmad3上面说的话。
通过在ArrayList中实现它,一个人可以很容易地知道 - ArrayList实现了哪些接口,而不是去IList找到它实现了ICollection和IEnumerable。
这避免了来回继承链的需要。
编辑:在基本层面上,一个接口实现另一个接口不能提供实现。从IList派生的类(因此间接实现ICollection和IEnumerable)也是如此。因此,即使您编写自己的实现IList的类(并且在声明中没有添加ICollection、IEnumerable),您将看到它将不得不为ICollection和IEnumerable提供实现。
而workmad3的推理是有道理的。
IFoo
有成员函数Woozle
,并且IDeluxeFoo
继承了IFoo
,实现IDeluxeFoo
的类可以显式地实现IDeluxeFoo.Woozle
或IFoo.Woozle
中的任何一个;这两个定义是同义的。如果实现IDeluxeFoo
的类的CLR没有明确指定它实现了IFoo
,我不知道CLR是否会识别IFoo.Woozle
的实现。 - supercat