构建通用集合类

发布于 2024-09-18 11:53:09 字数 736 浏览 3 评论 0原文

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

    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' 的操作数”。

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

任何帮助表示赞赏。谢谢。

I am building the following class to manage a dictionary.

    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);
        }              
    }

But I am getting an error "Operator '==' cannot be applied to operands of type 'TValue' and 'TValue'".

BTW, I am making this custom collection is because my dictionary has unique value, but I can't get key by value from a dictionary.

Any help is appreciated. Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

指尖上的星空 2024-09-25 11:53:10

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

you can use if (kvp.Value.Equals(value)) instead of ==.

毁梦 2024-09-25 11:53:10

泛型类型使用“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

Use the "where" condition on your generic types

class Dictionary<TKey,TVal>
    where TKey: IComparable, IEnumerable
    where TVal: MyI
{
    public void Add(TKey key, TVal val)
    {
    }
}

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

风透绣罗衣 2024-09-25 11:53:10

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

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");
    }
}

Don't create a new class. Create a extension method:

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");
    }
}
一向肩并 2024-09-25 11:53:10

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

具有 IEqualityComparer 类型的属性,该属性在构造函数中设置。

然后使用构造函数的一个版本来生成默认的 EqualityComparer.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);
    }              
}

If you want this to be general purpose, then you will want the definition of equality to be configurable, just as it is in the dictionary for keys.

Have a property of type IEqualityComparer<TValue>, which is set in the constructor.

Then have a version of the constructor that makes the default EqualityComparer<TValue>.Default. This will work by calling Equals on the type in question.

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);
    }              
}
嗫嚅 2024-09-25 11:53:09

您是否尝试过使用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);

Did you try using the Equals method?

if (kvp.Value.Equals(value))

I think this restriction is due to the fact that the == operator can't be used with all types. Take the following for instance:

struct Test
{
    public int Value;
}

Given the above struct, the following code will not compile:

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

However, all types have the Equals method, so calling that will work:

Test a, b;
a = b = new Test();
bool areEqual = a.Equals(b);
攀登最高峰 2024-09-25 11:53:09

弗雷德里克是对的;您需要使用Equals,因为您不能假定能够对所有类型使用==,因为并未为每种类型定义运算符。

根据您的场景,

where TValue : IEquatable<TValue>

在您的类上添加通用类型约束也可能是有意义的。原因是 object.Equals 接受另一个 object 作为参数,这意味着如果 TValue 是值类型,它将被装箱。另一方面,如果已知实现 IEquatable,则 Equals 可以解析为 IEquatable.Equals *,它采用 TValue 作为参数,因此不需要对值类型进行装箱。

我可能还建议您重新考虑此类的内部结构。就目前而言,您根本没有理由需要此类,因为您可以轻松地向 IDictionary 添加扩展方法,以通过枚举值按值查找键。我要做的是存储两个字典:一个 Dictionary 和一个 Dictionary,这样就可以在 O 中进行双向查找(1).

*顺便说一下,如果您好奇,您不能使用 IEquatable (或任何与此相关的接口)来确保类型已实现 < code>== 运算符的特点是运算符是静态,接口不能提供静态方法(因此不能提供运算符)。

Fredrik is right; you need to use Equals as you can't presume to be able to use == for all types, since the operator isn't defined for every type.

Depending on your scenario, it might also make sense to add

where TValue : IEquatable<TValue>

as a generic type constraint on your class. The reason for this is that object.Equals accepts another object as a parameter, which means that if TValue is a value type it will be boxed. If it can be known to implement IEquatable<TValue>, on the other hand, then Equals can be resolved to IEquatable<TValue>.Equals*, which takes a TValue as a parameter and therefore won't require value types to be boxed.

I might also recommend that you rethink the internal structure of this class. As it currently stands, there's no reason you need this class at all, as you could easily add an extension method to IDictionary<TKey, TValue> to find a key by value via enumeration over the values. What I would do instead is store two dictionaries: a Dictionary<TKey, TValue> and a Dictionary<TValue, TKey>, so that two-way lookup is possible in O(1).

*By the way, in case you're curious, the reason you can't use IEquatable<T> (or any interface for that matter) to ensure that a type has implemented the == operator is that operators are static, and interfaces cannot provide static methods (and thus can't provide operators).

柒七 2024-09-25 11:53:09

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

When you use generic comparsions I think you should implement a (x)CompareTo(Y) or a comparable class. Please correct me if im wrong.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文