Кто-нибудь может объяснить, почему Dictionary <> в C # не работает как map <T, U> в STL? - PullRequest
5 голосов
/ 05 марта 2010

Когда я впервые начал программировать на C # в прошлом году, я сразу же искал эквивалент карты STL и узнал о словаре.

ОБНОВЛЕНИЕ вычеркнул этот мусор ниже, я был совершенно не прав. Мой опыт работы с картой STL заключался в том, что я ненавидел, когда запрашивал его значение, и если ключа не было на карте, он автоматически создавал тип значения (независимо от того, что делал его конструктор по умолчанию) и добавлял его на карту. Затем я должен проверить это условие в коде и выдать исключение.

Словарь <> возвращает весь шебанг правильно - если ключа нет, он выдает исключение, если вы запрашиваете значение, или автоматически добавляет его, если его нет, и вы хотите установить значение.

Но вы все это уже знали. Я должен был написать свои модульные тесты, прежде чем писать здесь и смущать себя. :) Они написаны сейчас!

Теперь я люблю Dictionary и все, но больше всего меня беспокоит в этом вопросе прямо сейчас заключается в том, что если ключ отсутствует в словаре, он генерирует исключение KeyNotFoundException. Поэтому мне всегда нужно писать такой код:

Dictionary<string,string> _mydic;

public string this[string key]
{
  get {
    return _mydic[key]; // could throw KeyNotFoundException
  }
  set {
    if( _mydic.ContainsKey( key))
      _mydic[key] = value;
    else
      _mydic.Add( key, value);
  }
}

Почему Словарь не добавляет пару «ключ-значение» автоматически, если ключ не существует, как карта STL?

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

Ответы [ 3 ]

10 голосов
/ 05 марта 2010

Какое значение вы бы хотели вернуть, если его еще не было на карте? Он может вернуть default(TValue) - но тогда было бы несколько легко случайно использовать значение, если оно верное. Обратите внимание, что если вы хотите такое поведение, вы можете использовать:

get {
  string value;
  if (!_mydic.TryGetValue(key, out value))
    value = default(string);
  return value;
}

Я бы лично не рекомендовал это вообще, но если вы счастливы, что не можете провести различие (с помощью этого индексатора) между ключом с нулевым значением и отсутствующим ключом, это поможет. *

Обратите внимание, что ваш сеттер может быть намного проще - просто

_mydic[key] = value;

будет перезаписывать при необходимости.

3 голосов
/ 05 марта 2010

Я согласен, что обработка исключения является раздражающей, особенно для ссылочных типов, когда обычно имеет значение null. В любом случае вы можете использовать Dictionary<>.TryGetValue() для получения значения за один вызов.

0 голосов
/ 05 марта 2010

Я в замешательстве. Это здесь. документы даже говорят так:

When you set the property value, if the key is in the Dictionary(TKey, TValue), the value associated with that key is replaced by the assigned value. If the key is not in the Dictionary(TKey, TValue), the key and value are added to the dictionary.

и

KeyNotFoundException: The property is retrieved and key does not exist in the collection.

(нет упоминаний о том, что он был брошен во время задания).

...