Есть небольшое раздражение, которое я нахожу с большим количеством - у меня есть Dictionary<TKey, TValue>
, который содержит значения, которые могут быть или не быть.
Таким образом, нормальное поведение будет заключаться в использовании индексатора, например:
object result = myDictionary["key"];
Однако, если "key"
не находится в словаре, это бросает a 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
содержит намного больше кода.
Оба метода кажутся "грязными" - есть ли лучший способ сделать это уже в .Net?
Оба метода делают компромиссы, которые могут вызвать путаницу, но являются ли еще очевидными/ясными, чем другие? И почему?