Есть небольшое неудобство, с которым я сталкиваюсь - у меня есть Dictionary
, который содержит значения, которые могут или
Таким образом, нормальным поведением будет использование индексатора, например:
object result = myDictionary["key"];
Однако, если «ключ»
отсутствует в словаре, это вызывает исключение KeyNotFoundException
, поэтому вместо этого вы сделаете следующее:
object val;
if (!myDictionary.TryGetValue("key", out val))
{
val = ifNotFound;
}
Что нормально, за исключением того, что я могу загрузить их подряд - TryGetValue
начинает казаться ужасно неуклюжим.
Таким образом, вариант 1 является расширением method:
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
с неявным приведением из Dictionary
, но индексатор, который возвращает default (TValue)
вместо создания исключения KeyNotFoundException
.
Это позволяет мне сделать:
ForgivingDictionary<string, object> dict = myDictionary;
object val = dict["key"] ?? ifNotFound;
// do stuff to val, then...
dict["key"] = val;
Итак, теперь получаем и устанавливаем значения согласованы, но типы значений более беспорядочные, и ForgivingDictionary
включает намного больше кода.
Оба метода кажутся «беспорядочными» - есть ли лучший способ сделать это уже в .Net?
Оба методы идут на компромиссы, которые могут вызвать путаницу, но является ли один более очевидным / ясным, чем другой? И почему?