Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用自定义对象作为字典键_C# - Fatal编程技术网

C# 使用自定义对象作为字典键

C# 使用自定义对象作为字典键,c#,C#,我想使用自定义对象作为字典键,主要是这样的:(我不能使用.NET4.0,所以我没有元组) 类元组:IEquatable { 公共A AValue{get;set;} 公共B BValue{get;set;} 公共元组(aa,bb){AValue=A;BValue=B;} 公共布尔等于(元组) { 返回tuple.AValue.Equals(AValue)和&tuple.BValue.Equals(BValue); } 公共布尔等于(对象o) { 返回这个.Equals(o作为元组); } }

我想使用自定义对象作为字典键,主要是这样的:(我不能使用.NET4.0,所以我没有元组)

类元组:IEquatable
{
公共A AValue{get;set;}
公共B BValue{get;set;}
公共元组(aa,bb){AValue=A;BValue=B;}
公共布尔等于(元组)
{
返回tuple.AValue.Equals(AValue)和&tuple.BValue.Equals(BValue);
}
公共布尔等于(对象o)
{
返回这个.Equals(o作为元组);
}
}
然后我就这样做

  var boolmap = new Dictionary<Tuple<bool, bool>, string>();
  boolmap.Add(new Tuple<bool,bool>(true, true), "A");
  boolmap.Add(new Tuple<bool,bool>(true, false), "B");
  boolmap.Add(new Tuple<bool,bool>(false, true), "C");
  boolmap.Add(new Tuple<bool,bool>(false, false), "D");
  var str = boolmap[new Tuple<bool,bool>(true, false)];
var boolmap=newdictionary();
boolmap.Add(新元组(true,true),“A”);
boolmap.Add(新元组(true,false),“B”);
boolmap.Add(新元组(false,true),“C”);
boolmap.Add(新元组(false,false),“D”);
var str=boolmap[新元组(真、假)];
我在最后一行得到一个KeyNotFound异常。为什么会这样?我实现IEquatable还不够吗


谢谢

当您重写Equals方法时,您需要重写
GetHashCode
。更多说明可在此处找到:


您还需要重写
GetHashCode()
(最好也是
Equals()
)。否则相等的对象将返回不同的哈希代码,这意味着在查找时找不到该键

GetHashCode()
契约指定当两个对象被认为相等时,两个对象的返回值必须相等。这是你问题的根源;您的类不符合此要求。合同没有规定,如果不相等,则价值必须不同,但这将提高绩效。(如果所有对象都返回相同的哈希代码,那么从性能角度来看,您也可以使用平面列表。)

在您的情况下,一个简单的实现可能是:

public override int GetHashCode()
{
    return AValue.GetHashCode() ^ BValue.GetHashCode();
}
请注意,最好测试
AValue
BValue
是否为
null
。(这将有点复杂,因为您不约束泛型类型
A
B
,因此您不能只将值与
null
进行比较,例如,这些类型可能是值类型。)1

使您打算用作字典键的类不可变也是一个好主意。如果更改用作键的对象的值,字典将显示奇怪的行为,因为该对象现在位于不属于它的bucket中



1请注意,您可以在这里使用(类似于
BValue
),因为这将消除空检查的需要。

我只是重写了
GetHashCode
函数,但似乎即使
GetHashCode
返回了相同的值,更新也没有发生。
也等于
,一切都很有趣和好玩

你的get hash代码实现在哪里?如果你把a等于,你应该总是有一个get hash代码,你的代码会给你一个警告,而且是有原因的。当您修复该警告时,您将收到另一个警告-当您修复该警告时,您的代码将正常工作。永远不要忽视警告。你可能已经看到了:我想补充一点,为了让你的对象在字典中正确运行,有一套非常重要的强制性规则需要遵守。这里还有一个很好的参考:当两个对象返回不同的散列码时,系统会假定它们是不同的。当它们返回相同的散列码时,系统知道它们“可能”相等,因此调用object1.Equals(object2),并得出结论:如果Equals返回true,则它们相等;如果Equals返回false,则它们不同。如果不重写Equals对象,则调用Equals返回对象的引用,因此只有当两个对象是同一个对象时,才认为它们相等。
public override int GetHashCode()
{
    return AValue.GetHashCode() ^ BValue.GetHashCode();
}