哪个机制是更好的方式来扩展Dictionary来处理缺少的键,为什么? [英] Which mechanism is a better way to extend Dictionary to deal with missing keys and why?
问题描述
有一个小小的麻烦,我发现自己很多 - 我有一个字典< TKey,TValue>
,其中包含可能或可能不在的值。 p>
所以正常的行为是使用索引器,如下所示:
object result = myDictionary [key];
但是,如果key
不是在字典中,这会抛出一个 KeyNotFoundException
,所以你这样做:
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> ;
与字典< TKey,TValue>
中的隐式转换,但返回默认(TValue)
而不是抛出一个 KeyNotFoundException
。
让我来做:
ForgivingDictionary< string,object> dict = myDictionary;
对象val = dict [key] ?? ifNotFound;
//做东西val,然后...
dict [key] = val;
所以现在获取和设置值是一致的,但是值类型是messier和 ForgivingDictionary
涉及更多的代码。
这两种方法看起来都很混乱 - 有没有更好的方法来做这个.Net?
这两种方法都可能导致混淆,但是比另一种更明显/明确?为什么?
当命名用于替换现有方法的扩展方法时,我倾向于将方法名称添加到特定而不是缩短它:
GetValueOrDefault(...)
对于 ForgivingDictionary
,您可以约束 TKey
,以便它可以不是一个值类型。但是,如果您必须处理其中的值类型,那么您将返回一些值类型,最好的选项是返回 default(TKey)
,因为您可以't return null
。
老实说,我会使用扩展方法。
编辑: GetValueOrDefault()
,当然不会添加到字典,如果没有找到问题的关键。如果没有找到,我将返回一个默认值,因为它是如何命名的。如果有人想要插入,一个好的名字将是 GetValueOrInsertDefault()
。
There is a minor annoyance I find myself with a lot - I have a Dictionary<TKey, TValue>
that contains values that may or may not be there.
So normal behaviour would be to use the indexer, like this:
object result = myDictionary["key"];
However, if "key"
is not in the dictionary this throws a KeyNotFoundException
, so you do this instead:
object val;
if (!myDictionary.TryGetValue("key", out val))
{
val = ifNotFound;
}
Which is fine, except that I can have a load of these in a row - TryGetValue
starts to feel awful clunky.
So option 1 is an extension 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;
}
Which lets me do:
object result = myDictionary.TryGet("key1") ?? ifNotFound;
int i = anotherDictionary.TryGet("key2", -1);
Which is simple enough, but an additional extension method with a name similar to existing instance methods potentially adds confusion and reduces maintainability. It's also not consistent with the dictionary's indexer set - that will handle missing keys.
So option 2 is a new implementation of IDictionary<TKey, TValue>
with a implicit cast from Dictionary<TKey, TValue>
but an indexer that returns default(TValue)
instead of throwing a KeyNotFoundException
.
That let's me do:
ForgivingDictionary<string, object> dict = myDictionary;
object val = dict["key"] ?? ifNotFound;
// do stuff to val, then...
dict["key"] = val;
So now the get and set values are consistent, but value types are messier and ForgivingDictionary
involves a lot more code.
Both methods seem 'messy' - is there a better way to do this already in .Net?
Both methods make compromises that could cause confusion, but is one more obvious/clear than the other? And why?
When naming an extension method intended to replace an existing method, I tend to add to the method name for specificity rather than shortening it:
GetValueOrDefault(...)
As for the ForgivingDictionary
, you can constrain TKey
so that it can't be a value type. However, if you must deal with value types in it, you're going to return something for a value type and the best option is to return default(TKey)
since you can't return null
.
Honestly, I'd go with the extension method.
Edit: GetValueOrDefault()
, of course, wouldn't add to the dictionary if it didn't find the key. I would just return a default value if it wasn't found, because that's how it's named. If one wanted it to insert as well, a good name would be GetValueOrInsertDefault()
.
这篇关于哪个机制是更好的方式来扩展Dictionary来处理缺少的键,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!