哪种机制是扩展 Dictionary 来处理丢失键的更好方法?为什么?
我发现自己有一个小烦恼 - 我有一个 Dictionary
,其中包含可能存在或不存在的值。
因此,正常的行为是使用索引器,如下所示:
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
的新实现,具有来自 Dictionary
的隐式转换,但索引器返回 default(TValue )
而不是抛出 KeyNotFoundException
。
这让我来做:
ForgivingDictionary<string, object> dict = myDictionary;
object val = dict["key"] ?? ifNotFound;
// do stuff to val, then...
dict["key"] = val;
现在获取和设置值是一致的,但值类型更加混乱,并且 ForgivingDictionary
涉及更多代码。
这两种方法看起来都很“混乱”——.Net 中是否有更好的方法来做到这一点?
这两种方法都做出了妥协,可能会导致混乱,但其中一种是否比另一种更明显/清晰?为什么?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当命名旨在替换现有方法的扩展方法时,我倾向于添加方法名称以提高特异性,而不是缩短它:
对于
ForgivingDictionary
,您可以约束TKey
所以它不能是值类型。但是,如果您必须处理其中的值类型,则将返回值类型的某些内容,并且最好的选择是返回default(TKey)
因为您无法返回空
。老实说,我会选择扩展方法。
编辑:
GetValueOrDefault()
,当然,如果没有找到密钥,则不会添加到字典中。如果没有找到,我只会返回一个默认值,因为它就是这样命名的。如果也希望它插入,一个好的名称是GetValueOrInsertDefault()
。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:
As for the
ForgivingDictionary
, you can constrainTKey
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 returndefault(TKey)
since you can't returnnull
.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 beGetValueOrInsertDefault()
.我无法从您的问题推断出找不到密钥时应该做什么。我可以想象在这种情况下什么都不应该做,但我也可以想象相反的情况。
无论如何,您描述的一系列 TryGetValue 语句的优雅替代方案是使用以下扩展方法之一。我提供了两个选项,具体取决于当字典不包含该键时是否应该执行某些操作:
有关如何使用它的示例代码是:
I'm unable to infer from your question what should be done when a key is not found. I can imagine nothing should be done in that case, but I can also imagine the opposite.
Anyway, an elegant alternative for a series of these TryGetValue-statements you describe, is using one of the following extension methods. I have provided two options, depending on whether something should be done or not when the dictionary does not contain the key:
Example code on how to use this is:
或者也许
Or perhaps