[英]Building a generic collection class
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'". 但我得到一个错误“运算符'=='不能应用于'TValue'和'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.
谢谢。
Did you try using the Equals
method? 你尝试过使用
Equals
方法吗?
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: 但是,所有类型都有
Equals
方法,因此调用它将起作用:
Test a, b;
a = b = new Test();
bool areEqual = a.Equals(b);
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. 你需要使用
Equals
因为你不能假设能够为所有类型使用==
,因为没有为每种类型定义运算符。
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. 原因是
object.Equals
接受另一个object
作为参数,这意味着如果TValue
是一个值类型,它将被装箱。 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. 另一方面,如果可以知道实现
IEquatable<TValue>
,则可以将Equals
解析为IEquatable<TValue>.Equals
*,它将TValue
作为参数,因此不需要装箱值类型。
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. 按照目前的情况,你根本不需要这个类,因为你可以轻松地向
IDictionary<TKey, TValue>
添加一个扩展方法,通过对值的枚举来按值找到一个键。 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). 我要做的是存储两个词典:
Dictionary<TKey, TValue>
和Dictionary<TValue, TKey>
,以便在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). *顺便说一句,如果你很好奇,你不能使用
IEquatable<T>
(或任何接口)确保类型已经实现了==
运算符的原因是运算符是静态的 ,接口不能提供静态方法(因此不能提供运营商)。
When you use generic comparsions I think you should implement a (x)CompareTo(Y) or a comparable class. 当你使用泛型比较时,我认为你应该实现一个(x)CompareTo(Y)或类似的类。 Please correct me if im wrong.
如果我错了请纠正我。
Use the "where" condition on your generic types 在泛型类型上使用“where”条件
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 来自http://msdn.microsoft.com/en-us/library/6b0scde8%28VS.80%29.aspx
你可以使用if(kvp.Value.Equals(value))而不是==。
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");
}
}
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. 有一个
IEqualityComparer<TValue>
类型的属性,它在构造函数中设置。
Then have a version of the constructor that makes the default EqualityComparer<TValue>.Default
. 然后有一个构造函数的版本,它使默认的
EqualityComparer<TValue>.Default
。 This will work by calling Equals
on the type in question. 这将通过在相关类型上调用
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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.