我熟悉接口只包含方法,委托或事件的签名这一事实。方法的实现在实现接口的类中完成。实现接口的类必须实现其方法。
我创建了一个通用列表。当我浏览List的声明时,我看到它继承了ICollection,而ICollection有一个签名方法:object SyncRoot {get; } 为什么我看不到List类中的SyncRoot实现?
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>,
IList, ICollection, IEnumerable
{
public List();
public List(IEnumerable<T> collection);
public List(int capacity);
}
我希望在上面看到public object syncRoot()
?另外,如果我用JustDecompile(Telerik)打开它,我看到它已经实现但是private
。我错过了什么吗?
答案 0 :(得分:6)
这是@dtb指出的显式接口实现。这意味着,如果从SyncRoot
类型的引用中使用成员ICollection
,则该成员List
是可见的,而不是来自var l = new List<int>();
// compiler error
var sr1 = l.SyncRoot;
ICollection c = l;
// works
var sr2 = c.SyncRoot;
类型的引用
object ICollection.SyncRoot
{
...
}
这是显式接口实现的强大功能。如果由于某种原因,您想要为接口引用定义基本行为,但是为类引用定义了特殊行为(比如将返回类型更改为更具体,通常在普通重载中无效),您可以执行此操作这个。或者,如果您希望为遗留目的实现接口,但希望隐藏在实现中不再有用的方法或属性。
因此,如果您查看反编译代码,您将看到如下声明:
SyncRoot
因此,这为ICollection
接口实现了ICollection
,通过对List<T>
对象的任何ICollection
引用使其可见,但为任何其他对象隐藏它(非{ {1}})引用List<T>
对象。
在使用IEnumerable
等传统界面时,这也非常有用。例如,如果您想支持IEnumerable<T>
,则还必须支持IEnumerable
,但它们都有GetEnumerator()
种方法,这些方法因返回类型而异。例如:
public class MySpecialList<T> : IEnumerable<T>
{
// if we access from any other reference, we get the new, generic
// interface
public IEnumerator<T> GetEnumerator()
{
// your actual implementation
}
// so if we access from a reference of IEnumerable, we get older,
// non-generic interface
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
因为我们不能有两个返回不同值但具有相同签名的方法(重载),我们可以告诉类GetEnumerator()
在与IEnumerable
遗留引用一起使用时意味着一件事,并且所有其他参考文献完全不同(和更好)的东西:
var x = new MySpecialList<int>();
IEnumerable y = x;
// returns the generic enumerator
var genericEnum = x.GetEnumerator();
// since called from an IEnumerable, gets legacy enumerator
var legacyEnum = y.GetEnumerator();