【问题标题】:Why does IDictionary<TKey, TValue> extend ICollection<KeyValuePair<TKey, TValue>>?为什么 IDictionary<TKey, TValue> 扩展 ICollection<KeyValuePair<TKey, TValue>>?
【发布时间】:2014-02-19 17:47:04
【问题描述】:

我正在尝试为 .NET 4.0 创建自定义 ReadOnlyDictionary&lt;TKey, TValue&gt;。方法是保留一个私有的Dictionary&lt;TKey, TValue&gt; 对象以及标志以确定是否允许添加/删除和项目分配。

这很好,但我想实现IDictionary&lt;TKey, TValue&gt; 接口以确保完整性。但是,我注意到它扩展了ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;,而它的任何属性或方法都没有出现在Dictionary&lt;TKey, TValue&gt; 类中。这怎么可能?如果实现了接口,为什么ICollection成员不暴露?

另外,为什么Dictionary类首先需要实现ICollection

这是一个粗略的实现:

public sealed class ReadOnlyDictionary<TKey, TValue>:
    //IDictionary<TKey, TValue>,
    IEnumerable<KeyValuePair<TKey, TValue>>
{
    #region Members.

    public bool AllowListEdit { get; private set; }
    public bool AllowItemEdit { get; private set; }
    private Dictionary<TKey, TValue> Dictionary { get; set; }

    #endregion Members.

    #region Constructors.

    public ReadOnlyDictionary (bool allowListEdit, bool allowItemEdit) { this.AllowListEdit = allowListEdit; this.AllowItemEdit = allowItemEdit; this.Dictionary = new Dictionary<TKey, TValue>(); }
    public ReadOnlyDictionary (IEqualityComparer<TKey> comparer, bool allowListEdit, bool allowItemEdit) { this.AllowListEdit = allowListEdit; this.AllowItemEdit = allowItemEdit; this.Dictionary = new Dictionary<TKey, TValue>(comparer); }
    public ReadOnlyDictionary (IDictionary<TKey, TValue> dictionary, bool allowListEdit = false, bool allowItemEdit = false) : this(allowListEdit, allowItemEdit) { foreach (var pair in dictionary) { this.Dictionary.Add(pair.Key, pair.Value); } }
    public ReadOnlyDictionary (IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer, bool allowListEdit = false, bool allowItemEdit = false) : this(comparer, allowListEdit, allowItemEdit) { foreach (var pair in dictionary) { this.Dictionary.Add(pair.Key, pair.Value); } }

    #endregion Constructors.

    #region Properties.

    public int Count { get { return (this.Dictionary.Count); } }
    public IEqualityComparer<TKey> Comparer { get { return (this.Dictionary.Comparer); } }

    #endregion Properties.

    #region Methods.

    private void ThrowItemReadOnlyException () { if (this.AllowListEdit) { throw (new NotSupportedException("This collection does not allow editing items.")); } }
    private void ThrowListReadOnlyException () { if (this.AllowItemEdit) { throw (new NotSupportedException("This collection does not allow adding and removing items.")); } }
    public bool ContainsValue (TValue value) { return (this.Dictionary.ContainsValue(value)); }
    public void Clear () { this.ThrowListReadOnlyException(); this.Dictionary.Clear(); }

    #endregion Methods.

    #region Interface Implementation: IEnumerable<KeyValuePair<TKey, TValue>>.

    IEnumerator IEnumerable.GetEnumerator () { return (this.Dictionary.GetEnumerator()); }
    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator () { return (this.Dictionary.GetEnumerator()); }

    #endregion Interface Implementation: IEnumerable<KeyValuePair<TKey, TValue>>.

    #region Interface Implementation: ICollection<KeyValuePair<TKey, TValue>>.

    //public int Count { get { return (this.Dictionary.Count); } }
    //public bool IsReadOnly { get { return (this.AllowListEdit); } }

    //public bool Contains (KeyValuePair<TKey, TValue> item) { throw (new NotImplementedException()); }
    //public void Clear () { throw (new NotImplementedException()); }
    //public void Add (KeyValuePair<TKey, TValue> item) { throw (new NotImplementedException()); }
    //public void CopyTo (KeyValuePair<TKey, TValue> [] array, int arrayIndex) { throw (new NotImplementedException()); }
    //public bool Remove (KeyValuePair<TKey, TValue> item) { throw (new NotImplementedException()); }

    #endregion Interface Implementation: ICollection<KeyValuePair<TKey, TValue>>.

    #region Interface Implementation: IDictionary<TKey, TValue>.

    //====================================================================================================
    // Interface Implementation: IDictionary<TKey, TValue>.
    //====================================================================================================

    public Dictionary<TKey, TValue>.KeyCollection Keys { get { return (this.Dictionary.Keys); } }
    public Dictionary<TKey, TValue>.ValueCollection Values { get { return (this.Dictionary.Values); } }
    public TValue this [TKey key] { get { return (this.Dictionary [key]); } set { this.ThrowItemReadOnlyException(); this.Dictionary [key] = value; } }

    public void Add (TKey key, TValue value) { this.ThrowListReadOnlyException(); this.Dictionary.Add(key, value); }
    public bool ContainsKey (TKey key) { return (this.Dictionary.ContainsKey(key)); }
    public bool Remove (TKey key) { this.ThrowListReadOnlyException(); return (this.Dictionary.Remove(key)); }
    public bool TryGetValue (TKey key, out TValue value) { return (this.Dictionary.TryGetValue(key, out value)); }

    #endregion Interface Implementation: IDictionary<TKey, TValue>.
}

【问题讨论】:

    标签: c# .net dictionary collections readonly


    【解决方案1】:

    Dictionary&lt;TKey, TValue&gt;显式实现ICollection&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;接口。

    正如您在MSDN page for Dictionary 上看到的,这些方法列在“显式接口实现”下。

    显式实现接口意味着这些方法将无法通过具体类型使用。您必须将字典转换为 ICollection&lt;T&gt; 才能调用它们。

    Dictionary<int, int> dict = new Dictionary<int, int>();
    bool sync = dict.IsSynchronized; // not allowed
    
    ICollection<KeyValuePair<int, int>> dict = new Dictionary<int, int>();
    bool sync = dict.IsSynchronized; // allowed
    

    更多关于显式接口实现:http://msdn.microsoft.com/en-us/library/aa288461(v=vs.71).aspx

    【讨论】:

    • 谢谢。我知道显式接口,但没有想到这一点。那么问题来了,为什么字典要实现 ICollection 呢? IEnumerable 已经处理了迭代,不应该允许任意添加 KayValuePairs 对吧?
    • @RaheelKhan 好吧,我也没有看到实现ICollection 的很多优势。也许只是为了完整性和一致性(因为System.Collections 中的几乎每个集合都扩展了ICollection)?
    • 嗯。我认为集合初始化器会有意义,但 IDictionary 已经定义了相关的 Add 方法。没关系,对于垃圾邮件通知,我们深表歉意。
    • @dcastro:字典知道其中有多少项; ICollectionICollection&lt;T&gt; 可以报告该信息,但 IEnumerable&lt;T&gt; 不能。在设计Dictionary 时,继承自IEnumerable&lt;T&gt; 和带有Count 方法的接口的最不具体的接口是ICollection&lt;T&gt;
    猜你喜欢
    • 1970-01-01
    • 2011-01-16
    • 2012-07-25
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多