Отримання найкращої практики зі значення словника


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 робить внутрішній пошук, щоб знайти свій індекс. Якщо воно повертає true, вам потрібен інший пошук за індексом, щоб отримати фактичне значення. Коли ви використовуєте TryGetValue, він лише один раз шукає індекс, і якщо його знайде, він присвоює значення вашій змінній.

FYI: Це насправді не виявлення помилки.

Це дзвонить:

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 робить внутрішній пошук, щоб знайти свій індекс. Якщо воно повертає true, вам потрібен інший пошук за індексом, щоб отримати фактичне значення. Коли ви використовуєте 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;

Тож сподіваємось, ніде не спробуй / злови.

Я думаю, що це просто метод зручності насправді. Зазвичай я використовую його, оскільки він економить рядок-два рядка коду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.