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

在C#中能否对Dictionary实现一次查询完成存在性检查与取值?

解决方案

针对Dictionary中KeyValuePair是值类型无法直接和null比较的问题,有几种方式可以实现单次查询同时完成存在性检查与取值:

1. 使用可空结构体(C# 8.0+)

利用C#的可空值类型特性,把目标变量声明为可空键值对类型,直接判断是否为null即可(底层会自动处理值类型的默认值与null的映射):

Dictionary<(int X, int Y), ITileData<(int X, int Y)>> srchField = new();
KeyValuePair<(int X, int Y), ITileData<(int X, int Y)>>? next;
while ((next = srchField.FirstOrDefault(x => !x.Value.Reached)) != null)
{
    // 使用next.Value获取找到的键值对
    var targetItem = next.Value;
    // ...
}

2. 自定义扩展方法规避默认值误判

如果字典中可能存在键/值为默认值的元素,担心FirstOrDefault返回的默认实例被误判为有效元素,可以写一个扩展方法直接返回可空结果:

public static class EnumerableExtensions
{
    public static KeyValuePair<TKey, TValue>? FirstOrDefaultNullable<TKey, TValue>(
        this IEnumerable<KeyValuePair<TKey, TValue>> source,
        Func<KeyValuePair<TKey, TValue>, bool> predicate)
    {
        foreach (var item in source)
        {
            if (predicate(item))
                return item;
        }
        return null;
    }
}

使用方式和你熟悉的引用类型模式完全一致,且只会遍历集合一次:

KeyValuePair<(int X, int Y), ITileData<(int X, int Y)>>? next;
while ((next = srchField.FirstOrDefaultNullable(x => !x.Value.Reached)) != null)
{
    var targetItem = next.Value;
    // ...
}

3. 用Take(1)简化逻辑(无需扩展方法)

如果不想额外写扩展方法,也可以用Take(1)获取第一个匹配元素,通过foreach处理结果(序列最多包含一个元素):

while (true)
{
    var match = srchField.Where(x => !x.Value.Reached).Take(1);
    bool hasMatch = false;
    foreach (var next in match)
    {
        hasMatch = true;
        // 使用next处理找到的元素
        // ...
    }
    if (!hasMatch) break;
}

这种方式同样只遍历一次集合,找到第一个匹配元素后立即停止。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 11:05:22