考虑以下私人成员:
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
的冗余假实例或扫描所有字典。
有没有办法获得一个字典项,基于具有相同哈希码的对象以另一种更有效的方式?
答案 0 :(得分:1)
我认为你真的没有问题。但是让我们来看看(看看我推荐的结果)。
创建冗余假实例
创建新实例是一种相对便宜的操作。代码有点丑陋然后直接使用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
,并且你不必混淆重载(GetHashCode()
{ {1}})。
CollectionInfo
答案 1 :(得分:1)
有没有办法获得字典项,基于具有相同哈希码的对象另一种更有效的方式?
不幸的是没有。与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)
但他们没有。不幸的是,在类实现之外无法模拟类似的东西。
所以你会被提到的变通办法所困扰。我会选择假实例方法 - 至少你可以,有时没有这样的奢侈(如果类需要复杂的构造函数,强大的验证不允许伪实例化)。并等待MS开源BCL :-)
P.S。如何通过Guid
创建不同的字典呢?如果它已经包含在类的实例中,为什么要保留Guid
(16字节值类型)的2个副本?