2014-01-28 2 views
3

Я пытаюсь создать обычай ReadOnlyDictionary<TKey, TValue> для .NET 4.0. Подход состоит в том, чтобы сохранить частный объект Dictionary<TKey, TValue>, а также флаги, чтобы определить, разрешено ли добавление/удаление и назначение элемента.Почему IDictionary <TKey, TValue> расширяет ICollection <KeyValuePair <TKey, TValue >>?

Это прекрасно работает, но я хотел бы реализовать интерфейс IDictionary<TKey, TValue> для полноты. Однако я замечаю, что он расширяет ICollection<KeyValuePair<TKey, TValue>>, тогда как ни один из его свойств или методов не появляется в классе Dictionary<TKey, TValue>. Как это возможно? Если интерфейс реализован, почему 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>. 
} 

ответ

5

Dictionary<TKey, TValue> реализует интерфейс ICollection<KeyValuePair<TKey, TValue>>явно.

Как вы можете видеть на MSDN page for Dictionary, эти методы перечислены в разделе «Явные реализации интерфейса».

Явное внедрение интерфейса означает, что эти методы не будут доступны через конкретный тип. Вам нужно будет приложить словарь к ICollection<T>, чтобы иметь возможность называть их.

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

+0

Спасибо. Я знаю об явных интерфейсах, но не думал об этом. Вопрос в том, почему словарь должен реализовать ICollection вообще? IEnumerable уже заботится об итерации, и произвольное добавление KayValuePairs не должно быть разрешено? –

+0

@ RaheelKhan хорошо, я не вижу много преимуществ в реализации «ICollection». Возможно, просто для полноты и согласованности (поскольку почти каждая коллекция в 'System.Collections' расширяет' ICollection')? – dcastro

+0

Мех. Я думал, что инициализаторы коллекции имеют смысл, но IDictionary уже определяет соответствующий метод Add. Ничего, и извините за уведомление о спаме. – Rytmis

Смежные вопросы