Словарь C# TryGetValue со значениями int, как избежать двойного поиска

при выполнении чего-то вроде:

int value;
if (dict.TryGetValue(key, out value))
{
    if (condition)
    {
        //value = 0;  this copies by value so it doesn't change the existing value
        dict[key] = 0;
    }
}
else
{
    dict[key] = 0;
}

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

на отдельной заметке, Как и в части else{} моего кода, обычно считается хорошей практикой использовать индексатор при добавлении новых или замене старых значений и добавлять, чтобы было ясно, что вы добавляете, а не заменяете? Или должен ли я просто использовать индексатор каждый раз? Как я научился пользоваться словарем, я всегда выполняю поиск TryGetValue и в части else обрабатываю случаи, когда ключа не существует.

3 ответов


есть ли способ избежать поиска индекса для замены существующего значения?

не то, что я знаю - но доступ к словарю должен быть очень быстро, если у вас нет пользовательского класса, который переопределен GetHashCode плохо.

Если вы не видите проблемы с производительностью из-за двойного поиска, я бы оставил его в покое.


Я предпочитаю определять методы расширения удобства для таких вещей. Например:

    public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultValue)
    {
        TValue value;
        return dictionary.TryGetValue(key, out value) ? value : defaultValue;
    }

    public static TValue GetOrSet<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
    {
        return dictionary[key] = dictionary.GetValueOrDefault(key, value);
    }

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

int value = dict.GetOrSet(key, 0);

(отказ от ответственности: не выполняет if (condition) проверка-я редко испытываю эти сценарии)


вы можете попробовать это

Object value;
if (dict.TryGetValue(key, out value))
{
    if (condition)
    {
        //value.data = 0;  this copies by value so it doesn't change the existing value
        value.data = 0;
    }
}
else
{
    value.data = 0;
}

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