我有一个ConcurrentDictionary:
private static ConcurrentDictionary<int, string> _cd = new ConcurrentDictionary<int, string>();
保守一点,用于检索项目的实际密钥是一个对象,但我只是简单地使用其哈希代码作为密钥,以便(可能很大的)对象不是密钥:
public static string GetTheValue(Foo foo)
{
int keyCode = foo.GetHashCode(); // GetHashCode is overridden to guarantee uniqueness
string theValue = _cd.GetOrAdd(keyCode, FooFactory);
return theValue;
}
但是,在Factory中准备对象时,我需要Foo对象中的各种属性:
private static string FooFactory(Foo foo)
{
string result = null;
object propA = foo.A;
object propB = foo.B;
// ... here be magic to set result
return result;
}
由于GetOrAdd()的valueFactory参数需要Func<int, string>
,因此我无法将Foo对象传递给它。是否有可能这样做?
答案 0 :(得分:3)
使用大型对象作为密钥没有任何问题。
除非对象是struct
(并且它不应该是结构),否则永远不会被复制。
如果你打算以后能够查看,那么你的对象显然会被破坏,所以你不会泄漏记忆。
只要您有合理(或继承)的GetHashCode()
和Equals()
实施,就不会对性能产生任何影响。
答案 1 :(得分:2)
我认为这里有一个根本的误解:
保守,实际的关键 用于检索项目是一个对象 但我只是简单地使用它的哈希码 作为关键使a(可能 大)对象不是关键。
我加粗了我认为你认为相关的短语。他们真的不是。如果你把你的字典想象得太大,因为它的键是这些大对象,你就会把它想象成错误。对于引用类型(C#中的任何class
),键将仅作为引用存储在字典中,这是一个高达整数的大小。如果你担心在方法之间传递密钥,那么:这不是你的想法。只会复制和传递引用,而不是对象本身。
所以我同意SLaks:首先使用你的Foo
类型(或其他任何名称)作为关键字。它会让你的生活变得更加简单。
答案 2 :(得分:0)
我出于不同的原因需要这个。如果有人的其他人像我一样在这里结束,那么就是这样做的:
public static string GetTheValue(Foo foo)
{
int keyCode = ...
string theValue = _cd.GetOrAdd(keyCode, (key => FooFactory(foo))); //key is not used in the factory
return theValue;
}