如何基于具有相同哈希码的对象获取字典项
本文关键字:对象 获取 字典 哈希码 何基于 | 更新日期: 2023-09-27 18:13:42
考虑以下私有成员:
private ConcurrentDictionary<CollectionInfo, ServiceInfo> _collectionsServicesMapping;
类CollectionInfo
覆盖并添加了一些额外的属性:
class CollectionInfo
{
public Guid InstanceId { get; set; }
public string CollectionName { get; set; }
public string WorkFlowName { get; set; }
public Guid DomainId { get; set; }
public override bool Equals(object obj)
{
return obj is CollectionInfo && (obj as CollectionInfo).InstanceId.Equals(InstanceId);
}
public override int GetHashCode()
{
return InstanceId.GetHashCode();
}
}
在我需要的上下文中,我正在通过InstanceId:
寻找CollectionInfo
private IRequestHandler GetServiceByInstanceId(Guid instanceId)
{
}
我看到两个可选的解决方案:
_collectionsServicesMapping.TryGetValue(new CollectionInfo() { InstanceId = instanceId }, out si)
_collectionsServicesMapping.FirstOrDefault(x => x.Key.InstanceId.Equals(instanceId));
但是这迫使我要么创建一个多余的假实例 CollectionInfo
类,要么扫描所有的字典。
是否有一种方法来获得一个字典项,基于一个对象,具有相同的哈希码在另一个更有效的方式?
是否有一种方法来获得一个字典项,基于一个对象,具有相同的哈希码在另一个更有效的方法?
不幸的是没有。与Philip Pittle的回答相反,我认为您(以及处于类似情况的任何人)确实有问题。我们是我称之为的太多封装的受害者,从Dictionary<TKey, TValue>
开始,然后是ConcurentDictionary<TKey, TValue>
。这两个类都可以很容易地公开像
IEnumerable<KeyValuePair<TKey, TValue>> GetItems(int hashCode)
或
bool TryGetValue(int hashCode, Func<TKey, bool> predicate, out TValue value)
但是他们没有。不幸的是,在类实现之外无法模拟类似的东西。
因此,您只能使用前面提到的解决方法。我将选择伪实例方法—至少您可以,有时没有这样的奢侈(如果类需要具有强验证的复杂构造函数,不允许伪实例化)。然后等待微软开源BCL:-)
注:如何通过Guid
创建不同的字典,为什么要保留Guid
(16字节值类型)的2个副本,如果它已经包含在一个类的实例中?
我不认为你真的有问题。但是让我们从头到尾看一遍(看我推荐的内容)。
创建一个冗余的假实例
创建一个新实例是一个相对便宜的操作。代码是不是比直接使用Guid更难看,当然。但如果你担心的是这个,你有很多选择:
//excention method (in some static class)
public static ServiceInfo GetServiceByGuid (
this ConcurrentDictionary<CollectionInfo, ServiceInfo> dic, Guid id){
ServiceInfo si;
dic.TryGetValue(new CollectionInfo() { InstanceId = id}, out si);
return si;
}
或
//implicit coversion operator (in CollectionInfo)
public static implicit operator CollectionInfo(Guid id){
return new CollectionInfo(new CollectionInfo() { InstanceId = id};
}
那么你可以把Guid instanceId
传递给字典的TryGetValue
方法。
扫描所有的字典
没有理由采取这种方法。从技术上讲,你只扫描键,而不是"整个"字典,但TryGetValue
将更高效,因为它可以利用哈希来快速找到你正在寻找的项目。
更改字典
在那之后,这就是我认为你想要的:
ConcurrentDictionary<Guid, Tuple<CollectionInfo, ServiceInfo>>
这样你仍然可以获得并发性,你可以基于guid (id)匹配CollectionInfo
/ServiceInfo
,并且你不必与超载(CollectionInfo
中的GetHashCode()
)混淆。
private IRequestHandler GetServiceByInstanceId(Guid instanceId)
{
Tuple<CollectionInfo,ServiceInfo> pair;
if (_collectionsServicesMapping.TryGetValue(instanceId, out pair))
{
return pair.Item2;
}
// whatever you want to return if instanceId wasn't found
return null;
}