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

为何以int[]为键时Dictionary.ContainsKey返回False?

问题分析与解决方案

你的问题核心在于数组作为Dictionary键时的相等性判断逻辑——.NET中的数组是引用类型,默认情况下Dictionary会用引用相等来判断键是否相同,而不是比较数组的内容。

具体来说,你在循环里创建的int[] i = {x,y}和最后用来检查的int[] z = {0,0}是两个完全独立的对象,哪怕它们的元素完全一致,Dictionary也会认为这是两个不同的键,所以ContainsKey(z)会返回false。


最简单的解决方案:用ValueTuple代替数组

从C# 7.0开始,ValueTuple是处理这种简单坐标场景的最优选择,它是值类型,默认的相等性判断就是基于元素值的,不需要额外代码:

修改字典的声明:

static Dictionary<(int x, int y), Tile> map = new Dictionary<(int x, int y), Tile>();

然后在循环和检查时直接使用值元组:

static bool GenerateMap() {
    for (int y = 0; y < 3; y++) {
        for (int x = 0; x < 3; x++) {
            Tile tile;
            // 直接用值元组作为键
            var key = (x, y);
            if(map.ContainsKey(key)) {
                tile = map[key];
                Console.WriteLine("Contains!");
            } else {
                tile = new Tile();
                tile.Generate();
                map.Add(key, tile);
            }
        }
    }
    // 用值元组检查
    if (map.ContainsKey((0, 0))) return true;
    return false;
}

这样修改后,(0,0)和循环中创建的(0,0)会被认为是相等的键,方法会正确返回true。


备选方案:自定义数组相等比较器

如果你必须使用数组作为键,可以给Dictionary传入一个自定义的IEqualityComparer<int[]>,让它根据数组内容判断相等:

首先实现比较器:

public class IntArrayEqualityComparer : IEqualityComparer<int[]>
{
    public bool Equals(int[] a, int[] b)
    {
        // 处理null情况
        if (a == null || b == null)
            return a == b;
        // 长度不同直接不相等
        if (a.Length != b.Length)
            return false;
        // 逐一比较元素
        for (int i = 0; i < a.Length; i++)
        {
            if (a[i] != b[i])
                return false;
        }
        return true;
    }

    public int GetHashCode(int[] arr)
    {
        if (arr == null) return 0;
        // 基于数组内容生成哈希码
        int hash = 17;
        foreach (int num in arr)
        {
            hash = hash * 31 + num.GetHashCode();
        }
        return hash;
    }
}

然后初始化字典时传入这个比较器:

static Dictionary<int[], Tile> map = new Dictionary<int[], Tile>(new IntArrayEqualityComparer());

这样原代码中的数组键就会根据内容判断相等,ContainsKey(z)也会返回true。


另一种备选:自定义坐标结构体

你还可以创建一个专门的Coordinate结构体来表示坐标,这样代码可读性更高,同时也能基于值判断相等:

public struct Coordinate
{
    public int X { get; }
    public int Y { get; }

    public Coordinate(int x, int y) => (X, Y) = (x, y);

    // 重写相等性判断方法
    public override bool Equals(object obj)
    {
        return obj is Coordinate coord &&
               X == coord.X &&
               Y == coord.Y;
    }

    public override int GetHashCode() => HashCode.Combine(X, Y);

    // 可以额外重载==和!=运算符,让代码更直观
    public static bool operator ==(Coordinate left, Coordinate right) => left.Equals(right);
    public static bool operator !=(Coordinate left, Coordinate right) => !(left == right);
}

然后字典声明为static Dictionary<Coordinate, Tile> map = new Dictionary<Coordinate, Tile>();,使用时创建new Coordinate(x, y)作为键即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 16:22:58