Получение передовых методов определения словарных значений

79

Я недавно заметил, Dictionary.TryGetValue(TKey key, out TValue value)и мне было любопытно, какой подход лучше для получения значения из Словаря.

Я традиционно делал:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];
     ...

если я не знаю , что должно быть там.

Лучше просто сделать:

if (myDict.TryGetValue(somekey, out someVal)
    ...

Какая практика лучше? Один быстрее другого? Я мог бы предположить, что версия Try будет медленнее, поскольку она «проглатывает» внутри себя try / catch и использует это как логику, нет?

Николас Манкузо
источник

Ответы:

84

TryGetValue немного быстрее, потому что FindEntry будет вызываться только один раз.

Насколько быстрее? Это зависит от имеющегося набора данных. Когда вы вызываете метод Contains, Dictionary выполняет внутренний поиск, чтобы найти свой индекс. Если он вернет истину, вам потребуется еще один поиск по индексу, чтобы получить фактическое значение. Когда вы используете TryGetValue, он выполняет поиск индекса только один раз и, если он найден, присваивает значение вашей переменной.

К вашему сведению: на самом деле это не ошибка.

Звонит:

public bool TryGetValue(TKey key, out TValue value)
{
    int index = this.FindEntry(key);
    if (index >= 0)
    {
        value = this.entries[index].value;
        return true;
    }
    value = default(TValue);
    return false;
}

ContainsKey это:

public bool ContainsKey(TKey key)
{
    return (this.FindEntry(key) >= 0);
}
Мика
источник
TryGetValue немного быстрее, потому что FindEntry будет вызываться только один раз.
Джо
1
TryGetValue работает намного быстрее, если у вас большой словарь
Diadistis
4
Теоретически (ну, также и на практике) это не должно зависеть от размера словаря, поскольку ожидаемое (!) Время поиска постоянно, т.е. не зависит от размера словаря!
Конрад Рудольф
29

На самом деле TryGetValue быстрее. Насколько быстрее? Это зависит от имеющегося набора данных. Когда вы вызываете метод Contains, Dictionary выполняет внутренний поиск, чтобы найти свой индекс. Если он вернет истину, вам потребуется еще один поиск по индексу, чтобы получить фактическое значение. Когда вы используете TryGetValue, он выполняет поиск индекса только один раз и, если он найден, присваивает значение вашей переменной.

Редактировать:

Хорошо, я понимаю ваше замешательство, поэтому позвольте мне уточнить:

Случай 1:

if (myDict.Contains(someKey))
     someVal = myDict[someKey];

В этом случае есть 2 вызова FindEntry: один для проверки наличия ключа и один для его получения.

Случай 2:

myDict.TryGetValue(somekey, out someVal)

В этом случае есть только один вызов FindKey, потому что результирующий индекс сохраняется для фактического извлечения в том же методе.

Диадистис
источник
Согласовано. TryGetValue избавляет от необходимости выполнять поиск ключа дважды. Это также может помочь в случае многопоточности. Между тем, когда вы проверяете, существует ли значение, оно могло быть добавлено или удалено. Это может вызвать исключения «ключ уже существует» или «ключ не найден».
Брайан Рудольф
0

Я полагаю, что trygetvalue делает что-то вроде:

if(myDict.ReallyOptimisedVersionofContains(someKey))
{ 
  someVal = myDict[someKey];
  return true;
}
return false;

Так что, надеюсь, нигде не нужно пытаться / поймать.

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

Дженнифер
источник