在Wintellect的PowerCollections中,有一个GetValueElseAdd
,其工作原理如下:
if ( collection.GetValueElseAdd( key, ref value))
{
// just added, value unmodified
}
或者
// factory method only gets called if the key is not present.
if ( collection.GetValueElseAdd( key, out value, () => thingFactory.CreateNew()))
{
// just added; value contains factory result
}
在这两种情况下,只有一个通过散列来隔离值所在的位置。 (有关权衡的更多讨论,请参阅What happens to C# Dictionary<int, int> lookup if the key does not exist?)
问题是,为什么像这样的功能没有进入BCL,特别是考虑到几乎所有其他的PowerCollections都被吸入了3.5 / LINQ并且新的集合在4.0中添加了?
是因为一般使用模式是一个只执行一次Add
而你通常只用大量的时间点击一个哈希表查找TryGetValue
路径的等价物吗?
是因为这在树中比在哈希表中更有价值(在网上可以only find this implementation但我认为它不仅仅是一个OrderedList集合)
编辑:另请参阅Fredrik回复评论中链接的帖子,该回复讨论了集合的Sychronized变体的多线程注意事项。
或者我还有另一个成语吗?如果只有彼得戈尔德在这里!
答案 0 :(得分:2)
单一责任原则是我能提出的唯一可能与GetValueElseAdd
争论的理由。方法名称表示该方法有两个职责:它尝试获取项目和,如果失败,则添加项目(我从未使用过PowerCollections,但我会假设{{1}在未找到密钥的情况下,使用创建的对象分配。)
如果我正在设计API,以及行为很容易创建和封装的事实,可能足以阻止我实现它。
一旦方法名称开始包含和,或, Else 之类的字样,我通常会尝试退后一步。这些对我来说是指示该方法可能有太多责任。