Я пытаюсь создать обычай 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>.
}
Спасибо. Я знаю об явных интерфейсах, но не думал об этом. Вопрос в том, почему словарь должен реализовать ICollection вообще? IEnumerable уже заботится об итерации, и произвольное добавление KayValuePairs не должно быть разрешено? –
@ RaheelKhan хорошо, я не вижу много преимуществ в реализации «ICollection». Возможно, просто для полноты и согласованности (поскольку почти каждая коллекция в 'System.Collections' расширяет' ICollection')? – dcastro
Мех. Я думал, что инициализаторы коллекции имеют смысл, но IDictionary уже определяет соответствующий метод Add. Ничего, и извините за уведомление о спаме. – Rytmis