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

泛型KeyValue(手动字典)键比较不兼容的类型约束问题咨询

解决泛型Dictionary中Key比较的问题

首先得说,你当前的代码有个小设计问题:你的KeyValueGeneric<T>把Key和Value都用了同一个泛型参数T,这意味着Key和Value必须是同一种类型,而真正的Dictionary是支持Key和Value不同类型的。所以第一步我们先把这个结构改成支持两个独立的泛型参数,这样更符合Dictionary的实际用途。

接下来就是你遇到的核心问题:泛型类型T默认没有定义==运算符的比较规则,编译器不知道怎么去比较两个T类型的实例。解决这个问题有两种常用的方案,我会分别说明,然后给出修改后的完整代码。

方案1:给Key类型添加IEquatable<TKey>约束(推荐)

这种方式类型安全,还能避免值类型的装箱操作,是比较规范的做法。我们需要:

  • 把KeyValueGeneric改成KeyValueGeneric<TKey, TValue>,分别指定Key和Value的类型
  • 给MyDictionaryGenerics<TKey, TValue>添加where TKey : IEquatable<TKey>约束,确保Key类型实现了相等比较的接口
  • 把比较逻辑从==改成调用Equals方法

方案2:使用object.Equals进行比较(无约束)

如果你不想给Key类型加约束,可以直接用object.Equals方法,它能兼容所有类型(包括值类型和引用类型),但对于值类型会有轻微的装箱开销。

修改后的完整代码(方案1,推荐版)

class Generic_Key_Value
{
    // 改成两个泛型参数,分别对应Key和Value的类型
    public struct KeyValueGeneric<TKey, TValue>
    {
        public readonly TKey Key;
        public readonly TValue Value;

        public KeyValueGeneric(TKey key, TValue value)
        {
            Key = key;
            Value = value;
        }
    }

    // 同样使用两个泛型参数,并且给TKey添加IEquatable<TKey>约束
    public class MyDictionaryGenerics<TKey, TValue> where TKey : IEquatable<TKey>
    {
        public KeyValueGeneric<TKey, TValue>[] keyArray = new KeyValueGeneric<TKey, TValue>[20];
        public int Counter = 0;

        public TValue this[TKey key]
        {
            set
            {
                bool matchFound = false;
                for (int i = 0; i < Counter; i++)
                {
                    // 使用Equals方法进行比较,符合IEquatable<TKey>的约束
                    if (key.Equals(keyArray[i].Key))
                    {
                        keyArray[i] = new KeyValueGeneric<TKey, TValue>(key, value);
                        matchFound = true;
                        break; // 找到匹配后可以直接跳出循环,提升效率
                    }
                }
                if (!matchFound)
                {
                    keyArray[Counter] = new KeyValueGeneric<TKey, TValue>(key, value);
                    Counter++;
                }
            }
            get
            {
                for (int i = 0; i < Counter; i++) // 这里改成Counter而不是keyArray.Length,避免遍历空元素
                {
                    if (key.Equals(keyArray[i].Key))
                    {
                        return keyArray[i].Value;
                    }
                }
                throw new System.Collections.Generic.KeyNotFoundException();
            }
        }
    }
}

额外优化点说明

  • 我把getter里的循环上限从keyArray.Length改成了Counter,因为keyArray的长度是20,但实际存储的元素只有Counter个,这样能避免遍历空元素,提升效率
  • 在setter的循环里找到了匹配项后添加了break,不用继续遍历后面的元素

如果你想用方案2(无约束)

只需要把MyDictionaryGenerics的约束去掉,然后把比较代码改成:

if (object.Equals(key, keyArray[i].Key))

这样即使Key类型没有实现IEquatable<TKey>,也能正常进行相等比较。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:47:46