You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Dictionary<TKey,TValue>的TryGetKey功能?

在Dictionary中高效获取实际存储的键

问题背景

我需要在使用忽略大小写比较器的Dictionary<string, string>中,获取字典实际存储的键(比如传入小写的"ch",要拿到字典里的"CH"),类似HashSet<TKey>.TryGetValue的功能,但Dictionary<TKey, TValue>.TryGetValue只能返回对应的值,无法拿到原始键。同时我不想通过遍历所有键值对来实现,希望有高效的方案。

示例场景:

Dictionary<string, string > _countryNames = new(StringComparer.OrdinalIgnoreCase)
{
    {"CH", "Switzerland"}, {"DE", "Germany"}, {"US", "USA"}
};

// 传入"ch",期望返回"CH"
string GetValidIsoCountry(string countryCode)
{
    if (!_countryNames.ContainsKey(countryCode))
    {
        return null;
    }
    
    // 此处需要获取实际存储的键,而非传入的countryCode
}

高效解决方案

方法1:使用.NET 6+的CollectionsMarshal(推荐)

利用System.Runtime.InteropServices.CollectionsMarshal提供的GetDictionaryEntryRefOrNullRef方法,直接访问字典内部的哈希桶,无需遍历即可定位到目标键值对,效率和TryGetValue一致。

using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

public static class DictionaryExtensions
{
    public static bool TryGetActualKey<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, out TKey actualKey)
    {
        if (dictionary == null)
            throw new ArgumentNullException(nameof(dictionary));

        // 获取对应键值对的引用,不存在则返回空引用
        ref var entry = ref CollectionsMarshal.GetDictionaryEntryRefOrNullRef(dictionary, key);
        if (!Unsafe.IsNullRef(ref entry))
        {
            actualKey = entry.Key;
            return true;
        }

        actualKey = default;
        return false;
    }
}

使用示例:

string GetValidIsoCountry(string countryCode)
{
    if (_countryNames.TryGetActualKey(countryCode, out string actualCode))
    {
        return actualCode;
    }
    return null;
}

方法2:维护配套的HashSet(兼容旧版本.NET)

如果你的项目使用的是.NET Framework或低版本.NET Core,可以同时维护一个和字典键对应的HashSet<string>,利用HashSet.TryGetValue获取实际键,逻辑简单且高效。

HashSet<string> _validCountryCodes = new(StringComparer.OrdinalIgnoreCase)
{
    "CH", "DE", "US"
};

Dictionary<string, string > _countryNames = new(StringComparer.OrdinalIgnoreCase)
{
    {"CH", "Switzerland"}, {"DE", "Germany"}, {"US", "USA"}
};

string GetValidIsoCountry(string countryCode)
{
    if (_validCountryCodes.TryGetValue(countryCode, out string actualCode))
    {
        return actualCode;
    }
    return null;
}

方法3:自定义字典类(适合小体量字典)

如果字典数据量不大,可以封装自定义字典类,直接提供获取实际键的方法,缺点是内部需要遍历键值对,效率较低。

public class DictionaryWithActualKey<TKey, TValue> : Dictionary<TKey, TValue>
{
    public DictionaryWithActualKey(IEqualityComparer<TKey> comparer) : base(comparer) { }

    public bool TryGetActualKey(TKey key, out TKey actualKey)
    {
        foreach (var kvp in this)
        {
            if (Comparer.Equals(kvp.Key, key))
            {
                actualKey = kvp.Key;
                return true;
            }
        }
        actualKey = default;
        return false;
    }
}

内容的提问来源于stack exchange,提问作者Tim Schmelter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:22:51