我有这样的字典:
Dictionary<MyCompositeKey, int>
显然MyCompositeKey
是我设计的一个实现IEqualityComparer
的类,因此具有GetHashCode
方法。
据我所知,词典使用键的哈希值来访问该值,所以这就是我的问题:
虽然我可以通过dict.TryGetValue(new MyCompositeKey(params))
轻松访问该值,但我希望在每次访问时摆脱new
开销。
出于这个原因,我想知道是否有办法直接从密钥的哈希值(我可以用非常低的开销计算)来访问该值。
答案 0 :(得分:2)
没有办法做到这一点。
请注意,可能会发生哈希冲突,因此Dictionary<,>
中可能存在与给定哈希匹配的许多键。我们需要Equals
来找出哪个(如果有的话)是正确的。
你谈论new
开销。你确定它对你来说很重要吗?
如果是,您可以考虑将MyCompositeKey
设为不可变 struct
而不是class
。在某些情况下可能会更快,从而无需垃圾收集器从内存中删除所有“松散”密钥。
如果MyCompositeKey
是struct
,则表达式new MyCompositeKey(params)
仅将所有params
加载到调用堆栈(或CPU寄存器或任何运行时数字最佳) )。
添加:如果您选择struct
,请考虑实施IEquatable<>
。它看起来像这样:
struct MyCompositeKey : IEquatable<MyCompositeKey>
{
// readonly fields/properties
public override bool Equals(object obj)
{
if (obj is MyCompositeKey)
return Equals((MyCompositeKey)obj); // unbox and go to below overload
return false;
}
public bool Equals(MyCompositeKey other) // implements interface, can avoid boxing
{
// equality logic here
}
public override int GetHashCode()
{
// hash logic here
}
}
答案 1 :(得分:1)
你做不到。
Dictionary<TKey, TValue>
使用您无法从课外访问的内部存储桶集合 - 它是private
。
正如您在source code中看到的,访问方法首先确定存储桶(根据哈希码),然后按索引访问项目:
public bool TryGetValue(TKey key, out TValue value)
{
int i = FindEntry(key);
if (i >= 0)
{
value = entries[i].value;
return true;
}
value = default(TValue);
return false;
}
private int FindEntry(TKey key)
{
if (buckets != null)
{
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next)
{
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key))
return i;
}
}
return -1;
}