2009-12-03 1 views
1

Рассмотрим следующий код, где каждая клавиша имеет идентичное значение:C# Dictionary: каждый ключ имеет идентичное значение - могу ли я удалить избыточность?

IDictionary<string, string> quarterbackDictionary = new Dictionary<string, string>(); 
quarterbackDictionary.Add("Manning", "Manning"); 
quarterbackDictionary.Add("Brady", "Brady"); 
quarterbackDictionary.Add("Rivers", "Rivers"); 

Мой вопрос:

  • Могу ли я удалить избыточность, так что я не должен повторять каждый строка в два раза, похожий на следующее:
IDictionary<string, string> quarterbackDictionary = new Dictionary<string, string>(); 
quarterbackDictionary.Add("Manning"); 
quarterbackDictionary.Add("Brady"); 
quarterbackDictionary.Add("Rivers"); 

FYI:

  • Я использую словарь, потому что я хочу, чтобы бросить на попытке вставить дубликат ключа.
  • A HashSet будет не попытаться вставить дубликат ключа.
+0

Почему «ключ == значение»? Почему бы не использовать 'd.Add (« Manning », null)' или 'HashSet', как предлагает driis? – dalle

ответ

1

Может быть, вы могли бы использовать метод расширения

public static class DictionaryExtensions 
{ 
    public static void Add(this Dictionary<string, string> dictionary, 
     string keyAndValue) 
    { 
     string value; 
     if (dictionary.TryGetValue(keyAndValue, out value)) 
     { 
      throw new Exception(); 
     } 

     dictionary.Add(keyAndValue, keyAndValue); 
    } 
} 
+0

Я думаю, что метод расширения - это путь, но я бы добавил его в HashSet. – philsquared

+0

Я бы предпочел добавить метод расширения в HashSet или реализовать свою собственную коллекцию, как это сделал driis. Но стартер темы, похоже, использовал словарь <,>, поэтому я решил использовать его для ответа. – mrydengren

+0

ОП (Джим) заявил: «Я использую словарь, потому что хочу бросить попытку вставить дубликат ключа». Если это единственная причина, я считаю, что HashSet лучше подходит. – philsquared

11

Вы можете обернуть HashSet<string> в свой собственный класс и попросить его создать исключение, если вы попытаетесь дважды добавить один и тот же ключ.

Это не будет много хлопот, чтобы определить, что класс, на самом деле, здесь возможно осуществление, что вы можете настроить в соответствии с вашими потребностями:

public class UniqueHashSet<T> : ICollection<T> 
    { 
     private readonly HashSet<T> innerSet = new HashSet<T>(); 

     public void Add(T item) 
     { 
      if (innerSet.Contains(item)) 
       throw new ArgumentException("Element already exists", "item"); 
      innerSet.Add(item); 
     } 

     public void Clear() 
     { 
      innerSet.Clear(); 
     } 

     public bool Contains(T item) 
     { 
      return innerSet.Contains(item); 
     } 

     public void CopyTo(T[] array, int arrayIndex) 
     { 
      innerSet.CopyTo(array, arrayIndex); 
     } 

     public bool Remove(T item) 
     { 
      return innerSet.Remove(item); 
     } 

     public int Count 
     { 
      get { return innerSet.Count; } 
     } 

     public bool IsReadOnly 
     { 
      get { return false; } 
     } 

     public IEnumerator<T> GetEnumerator() 
     { 
      return innerSet.GetEnumerator(); 
     } 

     IEnumerator IEnumerable.GetEnumerator() 
     { 
      return innerSet.GetEnumerator(); 
     } 
    } 

Как отмечают другие ответы, вы можете также сделать это метод расширения. Я думаю, что вы, безусловно, можете это сделать, если вам не нужно быть абсолютно уверенным, что вы не можете дважды добавить один и тот же элемент (если вы это сделаете методом расширения, все равно можно вызвать обычный метод .Add).

+0

-1: Я использую словарь, потому что хочу бросить попытку вставить дубликат ключа. –

+1

+1: Это хороший ответ. – dalle

+2

Вместо использования словаря <> почему бы вам не использовать HashSet <> и добавить функцию, которая генерирует исключение, если ключ уже существует или добавляет ключ к хешу? – Aaron

1

Наследовать от System.Collections.ObjectModel.Collection и переопределить InsertItem (который защищен).

Затем вы можете сделать свою двойную проверку и бросить, когда кто-то вставляет дублирующийся элемент. InsertItem вызывается для любого из методов, которые могут быть помещены в новый элемент: Добавить, Вставить и т. Д.

+0

Класс 'System.Collections.ObjectModel.Collection' по-прежнему является коллекцией на основе массива; поиск элементов в нем с использованием '.Contains()' займет линейное время. Привлекательность словаря заключается в том, что время поиска примерно постоянное. –

+0

Было бы интересно увидеть приложение настолько сильно оптимизированным, что это действительно имеет значение. –

3

Добавить метод расширения в HashSet, скажем AddUnique, который просто вызывает Add и выбрасывает, если return false.

+0

+1: Это тоже работает. –

1

Вы также можете унаследовать от System.Collections.ObjectModel.KeyedCollection.

class MyDictionary : KeyedCollection<string, string> 
{ 
    protected override string GetKeyForItem(string item) 
    { 
     return item; 
    } 
} 

var d = new MyDictionary(); 
d.Add("jones"); 
d.Add("jones"); // this will except 
+0

+1 «KeyedCollection» может использоваться в .NET 2.0. 'Hashset' доступен только в .NET 3.5. –

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

  • Нет связанных вопросов^_^