了解ICollection实现和接口

时间:2012-01-04 15:57:23

标签: c#

我熟悉接口只包含方法,委托或事件的签名这一事实。方法的实现在实现接口的类中完成。实现接口的类必须实现其方法。

我创建了一个通用列表。当我浏览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。我错过了什么吗?

1 个答案:

答案 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();