Есть небольшое раздражение, которое я испытываю из-за большого количества вещей - у меня есть Dictionary<TKey, TValue>
, который содержит значения, которые могут быть или не быть там.
Так что нормальным поведением было бы использование индексатора, как это:
object result = myDictionary["key"];
Однако, если "key"
нет в словаре, выдается KeyNotFoundException
, поэтому вы делаете это вместо этого:
object val;
if (!myDictionary.TryGetValue("key", out val))
{
val = ifNotFound;
}
Что хорошо, за исключением того, что яможет загружать их подряд - TryGetValue
начинает чувствовать себя ужасно неуклюже.
Итак, вариант 1 - это метод расширения:
public static TValue TryGet<TKey, TValue>(
this Dictionary<TKey, TValue> input,
TKey key,
TValue ifNotFound = default(TValue))
{
TValue val;
if (input.TryGetValue(key, out val))
{
return val;
}
return ifNotFound;
}
, который позволяет мне делать:
object result = myDictionary.TryGet("key1") ?? ifNotFound;
int i = anotherDictionary.TryGet("key2", -1);
Это достаточно просто, но дополнительный метод расширения с именем, похожим на существующие методы экземпляра, потенциально добавляет путаницу и снижает удобство обслуживания.Это также не согласуется с набором индексаторов словаря - он будет обрабатывать недостающие ключи.
Таким образом, вариант 2 - это новая реализация IDictionary<TKey, TValue>
с неявным приведением от Dictionary<TKey, TValue>
, но индексатором, который вместо этого возвращает default(TValue)
бросить KeyNotFoundException
.
Что давайте мне сделать:
ForgivingDictionary<string, object> dict = myDictionary;
object val = dict["key"] ?? ifNotFound;
// do stuff to val, then...
dict["key"] = val;
Так что теперь значения get и set согласованы, но типы значений более запутанны, а ForgivingDictionary
включает в себя намного большеcode.
Оба метода кажутся «грязными» - есть ли лучший способ сделать это уже в .Net?
Оба метода идут на компромиссы, которые могут вызвать путаницу, но еще один очевидный / ясныйчем другой?И почему?