构建泛型集合类

时间:2010-09-07 06:42:28

标签: c# collections dictionary generics

我正在构建以下类来管理字典。

    public class EnumDictionary<TKey, TValue>
    {
        private Dictionary<TKey, TValue> _Dict;

        public EnumDictionary(Dictionary<TKey, TValue> Dict)
        {
            this._Dict = Dict;
        }

        public TKey GetValue(TValue value)
        {
            foreach (KeyValuePair<TKey, TValue> kvp in _Dict)
            {
                if (kvp.Value == value)
                    return kvp.Key;
            }

            throw new Exception("Undefined data type: " + value);
        }              
    }

但我收到错误“运营商'=='无法应用于'TValue'和'TValue'类型的操作数。”

顺便说一句,我正在制作这个自定义集合是因为​​我的字典具有独特的价值,但我无法从字典中获取键值。

感谢任何帮助。谢谢。

7 个答案:

答案 0 :(得分:5)

您是否尝试使用Equals方法?

if (kvp.Value.Equals(value))

我认为这种限制是因为==运算符不能用于所有类型。举例来说:

struct Test
{
    public int Value;
}

鉴于上述结构,以下代码将无法编译:

Test a, b;
a = b = new Test();
bool areEqual = a == b; // Operator '==' cannot be applied to 
                        // operands of type 'Test' and 'Test'

但是,所有类型都有Equals方法,因此调用它将起作用:

Test a, b;
a = b = new Test();
bool areEqual = a.Equals(b);

答案 1 :(得分:3)

Fredrik is right;您需要使用Equals,因为您不能假定能够对所有类型使用==,因为没有为每种类型定义运算符。

根据您的情况,添加

也可能有意义
where TValue : IEquatable<TValue>

作为类的泛型类型约束。这样做的原因是object.Equals接受另一个object作为参数,这意味着如果TValue是值类型,则会将其装箱。另一方面,如果可以知道实施IEquatable<TValue>,则可以将Equals解析为IEquatable<TValue>.Equals *,其中TValue作为参数,因此赢得了'{1}} t要求将值类型装箱。

我可能建议您重新考虑此类的内部结构。按照目前的情况,你根本不需要这个类,因为你可以轻松地向IDictionary<TKey, TValue>添加一个扩展方法,通过对值的枚举来按值找到一个键。我要做的是存储两个字典:Dictionary<TKey, TValue>Dictionary<TValue, TKey>,以便在O(1)中进行双向查找。

*顺便说一句,如果你很好奇,你不能使用IEquatable<T>(或任何接口)来确保类型已经实现了{{1}运算符是运算符 static ,接口不能提供静态方法(因此不能提供运算符)。

答案 2 :(得分:0)

当你使用泛型比较时,我认为你应该实现一个(x)CompareTo(Y)或类似的类。如果我错了,请纠正我。

答案 3 :(得分:0)

在通用类型

上使用“where”条件
class Dictionary<TKey,TVal>
    where TKey: IComparable, IEnumerable
    where TVal: MyI
{
    public void Add(TKey key, TVal val)
    {
    }
}

来自http://msdn.microsoft.com/en-us/library/6b0scde8%28VS.80%29.aspx

答案 4 :(得分:0)

你可以使用if(kvp.Value.Equals(value))而不是==。

答案 5 :(得分:0)

不要创建新类。创建扩展方法:

public static class DictionaryHelper
{
    public static TKey GetKeyFromValue<TKey, TValue>(this IDictionary<TKey, TValue> instance, TValue value)
    {
        foreach (var kvp in instance)
        {
            if (kvp.Value.Equals(value))
                return kvp.Key;
        }
        return default(TKey);
    }
}

public class Example
{
    public static void Main(string[] argv)
    {
        Dictionary<string, string> test = new Dictionary<string, string> { { "Mykey", "MyValue" }, { "Key1", "Value2" } };
        string key = test.GetKeyFromValue("MyValue");
    }
}

答案 6 :(得分:0)

如果您希望这是通用的,那么您将希望可以配置相等的定义,就像它在键的字典中一样。

拥有IEqualityComparer<TValue>类型的属性,该属性在构造函数中设置。

然后有一个构造函数的版本,使其成为默认的EqualityComparer<TValue>.Default。这可以通过在相关类型上调用Equals来实现。

public class EnumDictionary<TKey, TValue>
{
    private Dictionary<TKey, TValue> _Dict;
    private readonly IEqualityComparer<TValue> _cmp;

    public EnumDictionary(Dictionary<TKey, TValue> Dict, IEqualityComparer<TValue> cmp)
    {
        this._Dict = Dict;
        _cmp = cmp;
    }
    public EnumDictionary(Dictionary<TKey, TValue> Dict)
        :this(Dict, IEqualityComparer<TValue>.Default){}

    public TKey GetValue(TValue value)
    {
        foreach (KeyValuePair<TKey, TValue> kvp in _Dict)
        {
            if (cmp.Equals(kvp.Value, value))
                return kvp.Key;
        }

        throw new Exception("Undefined data type: " + value);
    }              
}