C# 从ConcurrentDictionary按键获取KeyValuePair(在O(1)时间内)

C# 从ConcurrentDictionary按键获取KeyValuePair(在O(1)时间内),c#,data-structures,concurrency,concurrentdictionary,C#,Data Structures,Concurrency,Concurrentdictionary,根据此解决方案(),我使用concurrentdirectionary作为缺少ConcurrentHashSet的解决办法。然而,我正在努力探索如何在O(1)时间内将原始T键从字典中取出 var cache=newConcurrentDictionary()); //... if(!cache.TryAdd(classInstance,Byte.MinValue)) 返回/*现有缓存项*/; 返回类实例; 有没有办法通过给ConcurrentDictionary条目一个等价的(IEquatab

根据此解决方案(),我使用
concurrentdirectionary
作为缺少
ConcurrentHashSet
的解决办法。然而,我正在努力探索如何在O(1)时间内将原始
T键
从字典中取出

var cache=newConcurrentDictionary());
//...
if(!cache.TryAdd(classInstance,Byte.MinValue))
返回/*现有缓存项*/;
返回类实例;
有没有办法通过给
ConcurrentDictionary
条目一个等价的(IEquatable)键来获取
KeyValuePair
(甚至仅仅是键),而不必在O(n)时间内对其进行枚举


我的问题出现是因为我用作键的对象彼此是
IEquatable
,而不是
ReferenceEqual
。如果
myDict.ContainsKey(someequalable)
,我想获取字典中的原始键实例(以及存储在其中的值),并扔掉当前的(重复的)实例。

我刚刚意识到我可以从使用
ConcurrentDictionary
切换到
ConcurrentDictionary
。它可能比字节值(未确认)占用更多的内存,但是如果值和键相同,我可以很容易地从值中获取键


要将此扩展到发现此问题的人以及实际使用“值”的人,您可以选择将词典更改为
concurrentdirectionary,这里有一个扩展方法,用于将值添加到用作
ConcurrentHashSet
concurrentdirectionary
(值等于键):


你看过这个方法了吗?另外,是否可以选择使用自定义而不是依赖类型的可均衡性?尝试检索用作键的实际对象是一种不可靠的想法
HashSet
也不允许您这样做。正如您所发现的,解决方案是将键对象存储为值。如果该值是引用类型,那么内存占用空间将不会比使用
字节时的内存占用空间大。阿兰你是对的,我误解了你的问题。关于劫持自定义等式比较器的
Equals
方法,不,我不认为我会这样建议。听起来太俗气了。:-)@JimMischel的
大小(字节)
(1)不是比
IntPtr.Size
(4-8)小吗?还要看一看这个方法:在集合中搜索给定的值并返回它找到的相等值(如果有的话)。@JimMischel你说得对!我刚刚对它进行了测试,一个
字典
与一个
字典
具有相同的内存占用(具有相同的项目数)。
var cache = new ConcurrentDictionary<MyEquatableClass, byte>());
//...
if(!cache.TryAdd(classInstance, Byte.MinValue))
    return /* Existing cache entry */;
return classInstance;
var cache = new ConcurrentDictionary<MyEquatableClass, MyEquatableClass>());
//...
if(!cache.TryAdd(classInstance, classInstance))
    return cache[classInstance];
return classInstance;
/// <summary>
/// Adds a value to a <see cref="ConcurrentDictionary{T,T}"/>
/// used as a concurrent <see cref="HashSet{T}"/>, if it does not already exist.<br/>
/// Returns the new value, or the existing value if the value exists.
/// </summary>
/// <param name="value">The value to be added, if it does not already exist.</param>
public static T GetOrAdd<T>(this ConcurrentDictionary<T, T> source, T value)
{
    return source.GetOrAdd(value, value);
}
var dict = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
Console.WriteLine($"dict.GetOrAdd(\"abc\"): {dict.GetOrAdd("abc")}");
Console.WriteLine($"dict.GetOrAdd(\"ABC\"): {dict.GetOrAdd("ABC")}");
Console.WriteLine($"dict.Count: {dict.Count}");