有没有一种类似于ConcurrentDictionary<TKey,TValue>Interlocked.Exchange<T>(...)的数据 struct ,可以让你原子地设置一个新值,并检索分配给任意键的旧值?AddOrUpdate(...)个过载都不可能.

推荐答案

此功能不包括在开箱即用中.GitHub DotNet/Runtime存储库中存在Transact方法的API proposal,这将提供此功能,但目前还没有产生太大的吸引力.不过,您可以使用基本的TryGetValueTryAddTryUpdate方法手动实现它:

public static TValue AddOrUpdate<TKey, TValue>(
    this ConcurrentDictionary<TKey, TValue> source,
    TKey key,
    Func<TKey, TValue> addValueFactory,
    Func<TKey, TValue, TValue> updateValueFactory,
    out bool oldValueExists,
    out TValue oldValue) where TKey : notnull
{
    ArgumentNullException.ThrowIfNull(source);
    ArgumentNullException.ThrowIfNull(addValueFactory);
    ArgumentNullException.ThrowIfNull(updateValueFactory);
    while (true)
    {
        if (source.TryGetValue(key, out oldValue))
        {
            TValue newValue = updateValueFactory(key, oldValue);
            if (source.TryUpdate(key, newValue, oldValue))
            {
                oldValueExists = true;
                return newValue;
            }
        }
        else
        {
            TValue newValue = addValueFactory(key);
            if (source.TryAdd(key, addValueFactory(key)))
            {
                oldValueExists = false;
                oldValue = default;
                return newValue;
            }
        }
    }
}

上述实现是现有AddOrUpdate实现的修改版本.

Csharp相关问答推荐

ASP.NET MVC购物车数量更新并从购物车中删除项目

如何使用C#中的图形API更新用户配置文件图像

如何创建ASP.NET Core主机并在同一进程中运行请求

一小时后,自定义缓存停止在App Insight中保存

如何使用CsvReader获取给定列索引的列标题?

. NET WireMock拒绝PostAsJsonAsync序列化

Mongo作为.NET中Testcontainers的副本集

ASP.NET核心REST API返回一个非常大的数字

如何测量在使用UTF8而不是C#中的UTF16编码字符串时内存使用量的增长

应用程序重新启动后,EFCore列表的BSON反序列化错误

TagHelpers在新区域不起作用

当空判断结果赋给变量时,为什么会出现可能空异常警告的解引用?

用C#从XML内部元素中获取特定值

Visual Studio,Docker容器-容器调用:连接被拒绝

流畅的验证--如何为属性重用规则?

SharpZipLib在文件名前加上目录名,生成tar.gz

.NET文档对继承的困惑

为什么C#中的类型别名不能在另一个别名中使用?

.NET6最小API:操作.MapGet之后的响应

在SQL中删除少于24小时的令牌