C# 构建泛型集合类
我正在构建下面的类来管理字典C# 构建泛型集合类,c#,collections,dictionary,generics,C#,Collections,Dictionary,Generics,我正在构建下面的类来管理字典 public class EnumDictionary<TKey, TValue> { private Dictionary<TKey, TValue> _Dict; public EnumDictionary(Dictionary<TKey, TValue> Dict) { this._Dict = Dict; }
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);
}
}
公共类枚举字典
{
私人词典;
公共词典(Dictionary Dict)
{
这个._Dict=Dict;
}
公钥GetValue(TValue值)
{
foreach(输入的键值对kvp)
{
如果(kvp.Value==值)
返回kvp.Key;
}
抛出新异常(“未定义的数据类型:”+值);
}
}
但是我得到一个错误“运算符'=''不能应用于'TValue'和'TValue'类型的操作数
顺便说一句,我制作这个自定义集合是因为我的字典有唯一的值,但我无法从字典中按值获取键
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);
}
}
感谢您的帮助。谢谢。您是否尝试过使用
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);
当您使用泛型比较时,我认为您应该实现(x)CompareTo(Y)或类似的类。如果我错了,请更正。在泛型类型上使用“where”条件
class Dictionary<TKey,TVal>
where TKey: IComparable, IEnumerable
where TVal: MyI
{
public void Add(TKey key, TVal val)
{
}
}
类字典
其中TKey:IComparable,IEnumerable
TVal:MyI在哪里
{
公共无效添加(TKey key,TVal val)
{
}
}
在中,可以使用if(kvp.Value.Equals(Value))代替==。;您需要使用Equals
,因为您不能假定能够对所有类型使用=
,因为没有为每个类型定义运算符
根据您的场景,添加
where TValue : IEquatable<TValue>
其中TValue:IEquatable
作为类的泛型类型约束。原因是object.Equals
接受另一个object
作为参数,这意味着如果TValue
是一种值类型,它将被装箱。另一方面,如果已知实现了IEquatable
,那么Equals
可以解析为IEquatable.Equals
*,它将TValue
作为参数,因此不需要对值类型进行装箱
我可能还建议您重新思考这个类的内部结构。就目前的情况而言,完全没有理由需要这个类,因为您可以轻松地向IDictionary
添加一个扩展方法,通过对值的枚举按值查找键。我要做的是存储两个字典:一个字典
和一个字典
,这样就可以在O(1)中进行双向查找
*顺便说一句,如果您感到好奇,您不能使用
IEquatable
(或任何相关接口)来确保类型实现了=
运算符的原因是运算符是静态的,接口不能提供静态方法(因此不能提供运算符)。不要创建新的类。创建扩展方法:
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");
}
}
公共静态类字典帮助器
{
公共静态TKey GetKeyFromValue(此IDictionary实例,TValue值)
{
foreach(实例中的var kvp)
{
如果(千伏值等于(值))
返回kvp.Key;
}
返回默认值(TKey);
}
}
公开课范例
{
公共静态void Main(字符串[]argv)
{
字典测试=新字典{{“Mykey”、“MyValue”}、{“Key1”、“Value2”};
字符串key=test.GetKeyFromValue(“MyValue”);
}
}
如果您希望它是通用的,那么您将希望平等的定义是可配置的,就像在键字典中一样
具有类型为IEqualityComparer
的属性,该属性在构造函数中设置
然后有一个使默认值等于comparer.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);
}
}
公共类枚举字典
{
私人词典;
私有只读IEqualityComparer\u cmp;
公共EnumDictionary(Dictionary Dict,IEqualityComparer cmp)
{
这个._Dict=Dict;
_cmp=cmp;
}
公共词典(Dictionary Dict)
:此(Dict,IEqualityComparer.Default){}
公钥GetValue(TValue值)
{
foreach(输入的键值对kvp)
{
如果(cmp.等于(kvp.值,值))
返回kvp.Key;
}
抛出新异常(“未定义的数据类型:”+值);
}
}
您试过了吗?奇怪的是,除非我添加约束:where TValue:class
-,否则我无法让它工作<代码>IEquatable也没有编译。@Kobi:无法获取工作内容?听起来你好像误解了我;如果添加where TValue:class
约束,则可以使==
工作,因为=
是为所有引用类型隐式定义的(它将只使用对象。ReferenceEquals
)。我在回答中建议的是,OP addwhere TValue:IEquatable
,这样Equals
方法就不会阻塞它的参数。是的,我确实试过这个,它对我来说就像预期的一样。明白了吗,还是我遗漏了什么?@Kobi:是的,我看了你的链接,你似乎认为我在说“如果你在TValue:IEquatable中添加,你可以使用=
操作符”。。。但我不是这么说的。希望现在更清楚了?或者你认为我应该改写我的答案吗?显然,我误解了你。抱歉,谢谢您的额外解释。只有在需要进行<或>比较时才需要此项。如果这样做,则应该实现IComparable接口和CompareTo()方法。其他