C# c“多键词典”;KeyNotFoundException“;用自己的可变类替换元组时
我声明了一个可变类,它作为元组的替换,作为字典的键。原因是序列化。序列化工作得很好。出现以下问题时,我在使用该类时得到一个“KeyNotFoundException”,但仅当该类的新实例用于查找时。要更清楚地说明这一点,请参见以下类定义:C# c“多键词典”;KeyNotFoundException“;用自己的可变类替换元组时,c#,dictionary,tuples,multikey,C#,Dictionary,Tuples,Multikey,我声明了一个可变类,它作为元组的替换,作为字典的键。原因是序列化。序列化工作得很好。出现以下问题时,我在使用该类时得到一个“KeyNotFoundException”,但仅当该类的新实例用于查找时。要更清楚地说明这一点,请参见以下类定义: public class STuple<T1, T2> { public T1 Item1 { get; set; } public T2 Item2 { get; set; } public static
public class STuple<T1, T2> {
public T1 Item1 { get; set; }
public T2 Item2 { get; set; }
public static implicit operator Tuple<T1, T2>(STuple<T1, T2> st)
{
return Tuple.Create(st.Item1, st.Item2);
}
public static implicit operator STuple<T1, T2>(Tuple<T1, T2> t)
{
return new STuple<T1, T2>()
{
Item1 = t.Item1,
Item2 = t.Item2,
};
}
public STuple()
{
}
public STuple(T1 t1, T2 t2) : this()
{
Item1 = t1;
Item2 = t2;
}
}
公共类愚蠢{
公共T1项1{get;set;}
公共T2项2{get;set;}
公共静态隐式运算符元组(STuple st)
{
返回Tuple.Create(st.Item1,st.Item2);
}
公共静态隐式运算符STuple(元组t)
{
返回新的愚蠢()
{
Item1=t.Item1,
第2项=t.2项,
};
}
公众愚蠢
{
}
公共麻木(T1,T2):这()
{
第1项=t1;
第2项=t2;
}
}
下面是示例程序:
Dictionary<Tuple<string, string>, double> TupleDic = new Dictionary<Tuple<string, string>, double>();
TupleDic.Add(new Tuple<string, string>("Name1", "Name2"), 5);
TupleDic.Add(new Tuple<string, string>("Name3", "Name4"), 10);
Console.WriteLine("dict-Entry 1: {0}", TupleDic[new Tuple<string, string>("Name1", "Name2")]);
Console.WriteLine("dict-Entry 2: {0}", TupleDic[new Tuple<string, string>("Name3", "Name4")]);
Dictionary<STuple<string, string>, double> STupleDic = new Dictionary<STuple<string, string>, double>();
STuple<string, string> STuple1 = new STuple<string, string>("Name1", "Name2");
STuple<string, string> STuple2 = new STuple<string, string>("Name3", "Name4");
STupleDic.Add(STuple1, 5);
STupleDic.Add(STuple2, 10);
//Still working
Console.WriteLine();
Console.WriteLine("Sdict-Entry 1: {0}", STupleDic[STuple1]);
Console.WriteLine("Sdict-Entry 2: {0}", STupleDic[STuple2]);
//Not working
STuple<string, string> STuple3 = new STuple<string, string>("Name1", "Name2");
STuple<string, string> STuple4 = new STuple<string, string>("Name3", "Name4");
Console.WriteLine();
Console.WriteLine("Sdict-Entry 1: {0}", STupleDic[STuple3]);
Console.WriteLine("Sdict-Entry 2: {0}", STupleDic[STuple4]);
Console.ReadKey();
Dictionary TupleDic=newdictionary();
添加(新元组(“名称1”、“名称2”)、5);
添加(新元组(“名称3”,“名称4”),10);
WriteLine(“dict条目1:{0}”,TupleDic[新元组(“Name1”,“Name2”));
WriteLine(“dict条目2:{0}”,TupleDic[新元组(“Name3”,“Name4”));
Dictionary STupleDic=新字典();
STuple STuple1=新的STuple(“名称1”、“名称2”);
STuple STuple2=新的STuple(“名称3”、“名称4”);
添加(STuple1,5);
添加(STuple2,10);
//还在工作
Console.WriteLine();
WriteLine(“Sdict条目1:{0}”,STupleDic[STuple1]);
WriteLine(“Sdict条目2:{0}”,STupleDic[STuple2]);
//不起作用
STuple STuple3=新的STuple(“名称1”、“名称2”);
STuple STuple4=新的STuple(“名称3”、“名称4”);
Console.WriteLine();
WriteLine(“Sdict条目1:{0}”,STupleDic[STuple3]);
WriteLine(“Sdict条目2:{0}”,STupleDic[STuple4]);
Console.ReadKey();
使用普通元组的示例工作得很好,但是当我使用自己的类STuple时,它只在我使用与用于添加的键完全相同的键(相同的实例)时工作。我是一个完全的初学者,有没有可能是因为一些值类型和引用类型的混淆而出现问题
在我看来真的很奇怪,使用foreach进行查找仍然有效:
Console.WriteLine();
foreach (KeyValuePair<STuple<string, string>, double> s in STupleDic)
{
Console.WriteLine("Sdict-Entry 1: {0}", s.Value);
}
Console.WriteLine();
foreach(STupleDic中的键值对)
{
WriteLine(“Sdict条目1:{0}”,s.Value);
}
警告:在可变结构上实现GetHashCode
会导致灾难。哈希代码只有一个目的,那就是方便在哈希表中存储。哈希表中用作键的项不应发生变化(用于计算哈希的任何属性),因为更改哈希代码会导致哈希表发生无法恢复的损坏。
为了使项在集合中工作,它们必须实现相等和hashcode成员。因此,您可以(感谢Resharper):
公共类愚蠢
{
公众愚蠢
{
}
公共停车场(T1、T2)
:此()
{
第1项=t1;
第2项=t2;
}
公共T1项1{get;set;}
公共T2项2{get;set;}
受保护的布尔等于(愚蠢的其他)
{
返回EqualityComparer.Default.Equals(Item1,other.Item1)&&
EqualityComparer.Default.Equals(Item2,other.Item2);
}
公共覆盖布尔等于(对象对象对象)
{
if(ReferenceEquals(null,obj))返回false;
if(ReferenceEquals(this,obj))返回true;
if(obj.GetType()!=GetType())返回false;
回报等于((愚蠢的)obj);
}
公共覆盖int GetHashCode()
{
未经检查
{
返回(EqualityComparer.Default.GetHashCode(Item1)*397)^
EqualityComparer.Default.GetHashCode(Item2);
}
}
公共静态布尔运算符==(向左暂停,向右暂停)
{
返回等于(左、右);
}
公共静态布尔运算符!=(向左暂停,向右暂停)
{
返回!等于(左,右);
}
公共静态隐式运算符元组(STuple st)
{
返回Tuple.Create(st.Item1,st.Item2);
}
公共静态隐式运算符STuple(元组t)
{
还新糊涂
{
Item1=t.Item1,
Item2=t.Item2
};
}
}
警告:在可变结构上实现GetHashCode
会导致灾难。哈希代码只有一个目的,那就是方便在哈希表中存储。哈希表中用作键的项不应发生变化(用于计算哈希的任何属性),因为更改哈希代码会导致哈希表发生无法恢复的损坏。
为了使项在集合中工作,它们必须实现相等和hashcode成员。因此,您可以(感谢Resharper):
公共类愚蠢
{
公众愚蠢
{
}
公共停车场(T1、T2)
:此()
{
第1项=t1;
第2项=t2;
}
公共T1项1{get;set;}
公共T2项2{get;set;}
受保护的布尔等于(愚蠢的其他)
{
返回EqualityComparer.Default.Equals(Item1,other.Item1)&&
EqualityComparer.Default.Equals(Item2,other.Item2);
}
公共覆盖布尔等于(对象对象对象)
{
if(ReferenceEquals(null,obj))返回false;
if(ReferenceEquals(this,obj))返回true;
if(obj.GetType()!=GetType())返回false;
回报等于((愚蠢的)obj);
}
公共覆盖int GetHashCode()
{
未经检查
{
返回(EqualityComparer.Default.GetHashCode(Item1)*397)^
EqualityComparer.Default.GetHashCode(Item2);
public class STuple<T1, T2>
{
public STuple()
{
}
public STuple(T1 t1, T2 t2)
: this()
{
Item1 = t1;
Item2 = t2;
}
public T1 Item1 { get; set; }
public T2 Item2 { get; set; }
protected bool Equals(STuple<T1, T2> other)
{
return EqualityComparer<T1>.Default.Equals(Item1, other.Item1) &&
EqualityComparer<T2>.Default.Equals(Item2, other.Item2);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((STuple<T1, T2>) obj);
}
public override int GetHashCode()
{
unchecked
{
return (EqualityComparer<T1>.Default.GetHashCode(Item1)*397) ^
EqualityComparer<T2>.Default.GetHashCode(Item2);
}
}
public static bool operator ==(STuple<T1, T2> left, STuple<T1, T2> right)
{
return Equals(left, right);
}
public static bool operator !=(STuple<T1, T2> left, STuple<T1, T2> right)
{
return !Equals(left, right);
}
public static implicit operator Tuple<T1, T2>(STuple<T1, T2> st)
{
return Tuple.Create(st.Item1, st.Item2);
}
public static implicit operator STuple<T1, T2>(Tuple<T1, T2> t)
{
return new STuple<T1, T2>
{
Item1 = t.Item1,
Item2 = t.Item2
};
}
}