C # оптимальное использование IDictionary для поиска с возможностью не найден - PullRequest
8 голосов
/ 28 февраля 2012

Допустим, у меня есть следующий метод:

internal MyClass GetValue(long key)
{
  if (_myDictionary.ContainsKey(key))
    return _myDictionary[key];

  return null; // Not found
}

IDictionary<long,MyClass> _myDictionary=...

Но в приведенном выше коде есть два поиска в словаре:

  1. Проверка на наличие ключа
  2. Фактическое извлечение значения

Существует ли более оптимальный способ сформулировать такую ​​функцию, чтобы выполнялся только один поиск, но случай «не найден» по-прежнемуобрабатывается с помощью нулевого возврата (т. е. не с помощью не найденного исключения)?

Например, было бы неплохо, если бы поиск ключа возвратил какой-то итератор, который можно использовать для получения значения, или недействительный итератор, если значение не было найдено, как это делается в C ++.Возможно C # имеет лучший способ сделать это, учитывая его языковые особенности.

Ответы [ 3 ]

16 голосов
/ 28 февраля 2012

Метод TryGetValue был разработан именно для этого сценария - чтобы избежать двух операций поиска.

Этот метод сочетает в себе функциональность метода ContainsKey и свойства Item..

Если ключ не найден, то параметр значения получает соответствующее значение по умолчанию для типа значения TValue.

[...] Используйте метод TryGetValue, если ваш код часто пытаетсяключи доступа, которых нет в словаре.Использование этого метода более эффективно, чем перехват KeyNotFoundException, генерируемого свойством Item.

internal MyClass GetValue(long key)
{
    MyClass maybeValue;

    // Normally, one would inspect the return value of this method
    // but in this case, it's not necessary since a failed lookup
    // will set the out argument to default(valType), which is null
    // for a reference type - exactly what you want.
   _myDictionary.TryGetValue(key, out maybeValue);

    return maybeValue; 
}
2 голосов
/ 28 февраля 2012

набирает SPFiredrakes идею ...

public static class Extensions
{ 
    public static TValue GetValueOrDefault<TKey, TValue>(
            this IDictionary<Tkey, TValue> iDictionary, Tkey key)
    {
        TValue result;
        return iDictionary.TryGetValue(key, out result) ? result : default(TValue)
    }
}

используется вот так

var d = new Dictionary<long, SomeType> 
    {{1, new SomeType()}, {42, new SomeType()}, ...}

var value1 = d.GetValueOrDefault(1);
var value42 = d.GetValueOrDefault(42);
var valueX = d.GetValueOrDefault(10);

Конечно, теперь вы должны проверить, равны ли ваши значения null, возможно, именно поэтому .Net команда пропустила эту функцию.

1 голос
/ 28 февраля 2012

Вместо этого следует использовать TryGetValue - он использует один поиск.

internal MyClass GetValue(long key) {
    MyClass  res = null;
    _myDictionary.TryGetValue(key, out res)
    return res;
}

Вызов достаточно короткий, чтобы использовать "inline", без добавления функции-оболочки.TryGetValue возвращает bool, указывающее, был ли поиск успешным или нет.

...