如何使用 CollectionsMarshal 在 .NET 6 或 .NET 7 中实现 HashSet.GetOrAdd(T) 扩展方法

问题描述 投票:0回答:1

在 dotnet runtime Github repo 上有a proposal for adding

HashSet.GetOrAdd(T)
- similar to

public static T GetOrAdd<T>(this HashSet<T> hashSet, T equalValue)
{
    if (hashSet.TryGetValue(equalValue, out var actualValue))
        return actualValue;

    hashSet.Add(equalValue);
    return equalValue;
}

但没有重复的哈希查找(性能影响)。

该问题已通过以下决议解决:

我们正在为 #15059 走 CollectionsMarshal 路线,我们 应该为 HashSet 考虑类似的方法

在 issue #15059 最后一条评论有一个 CollectionsMarshal 用于 Dictionary 的例子:

public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TValue> valueFactory)
where TKey : notnull
{
    if (dictionary == null)
        throw new ArgumentNullException(nameof(dictionary));

    if (valueFactory == null)
        throw new ArgumentNullException(nameof(valueFactory));            

    ref TValue? value = ref CollectionsMarshal.GetValueRefOrAddDefault(dictionary, key, out bool exists);
    if (!exists)
        value = valueFactory(key);

    return value!;
}

我尝试使用相同的方法来实现

HashSet.GetOrAdd(T)
扩展但失败了 - 我不知道如何为 CollectionsMarshal.GetValueRefOrAddDefault() 方法获取
key
值。

这两个问题都被锁定为已解决并仅限于合作者 - 所以我不能直接在那里提问。

c# .net marshalling hashset
1个回答
0
投票

MS的答案(只能创建执行双重查找的扩展方法):

郑重声明,使用 CollectionsMarshal for HashSet 被证明是 不可行,因为你不能对键进行引用返回 - #82840(评论)

也就是说,共识是 HashSet 的 GetOrAdd 方法是 与仅使用 HashSet.Add 相比不是特别有价值,除了 对于需要访问实际实例的罕见情况 存储在 HashSet 中 - #82875(评论)

© www.soinside.com 2019 - 2024. All rights reserved.