更确切地说,我有这样的事情:
Dictionary<KeyValuePair<MyState, MyAction>, float> Dict =
new Dictionary<KeyValuePair<MyState, MyAction>, float>();
稍后,我有一个自定义的KeyValuePair对象;
KeyValuePair<MyState, MyAction> kvp =
new KeyValuePair<MyState, MyAction>(new MyState(...), new MyAction(...));
我的问题是:如果kvp状态和动作与Dict中的一对具有完全相同的值(在Dict中存在具有与kvp MyAction相同的MyState的KeyValuePair,并且来自Dict的MyAction具有完全相同的值, kvp中的MyAction)。唯一的区别是参考不同。
长话短说,有2个KeyValuePairs对象,两个都具有相同的值(不同的引用),如何从Dict获取浮点值,而不必迭代整个字典只是为了手动比较每个key.key和key。值只是为了看看密钥是否实际相同:
foreach(var StAct in Dict)
if(StAct.Key.Key.Equals(kvp.Key) &&
StAct.Key.Value.Equals(kvp.value))
//where StAct.Key.Key is the MyState object and StAct.Key.Value is the MyAction object
{
MessageBox.Show(StAct.Value + "");
break;
}
答案 0 :(得分:2)
您需要确保在MyState对象中作为Dictionary的键,您已正确覆盖了Equals()和GetHashCode()方法。
正如您所注意到的,类的默认行为是检查引用相等性,因此如果您想要某些不同的行为,则必须自己提供。
public class MyState
{
public override bool Equals(object obj)
{
// your equality implementation goes here
}
public override int GetHashCode()
{
// your hashcode implementation goes here
}
}
创建一个行为良好的GetHashCode()方法并不一定是微不足道的,但你可以在这个答案中找到一些关于如何做到这一点的好建议:https://stackoverflow.com/a/371348/5438433
完成后,您只需写下:
if(dict.ContainsKey(kvp.Key)) {.....}
答案 1 :(得分:0)
您需要在GetHashCode()
级上实施Equals()
和KeyValuePair<>
。这些是Dictionary<>
用于查找密钥的方法。
规则是,如果覆盖GetHashCode()
,则必须覆盖Equals()
,因为必须确保两个“相等”对象始终生成相同的哈希码。这是Dictionary<>
正常工作所必需的。
Dictionary<>
首先通过搜索其哈希码来查找正确的密钥,然后才使用Equals()
来确保它找到了正确的密钥。
但是,可以对于不相等的对象具有相同的哈希码。例如,通过始终返回GetHashCode()
来实现1
是完全合法的,因为它满足相等对象具有相同哈希码的规则。但是,它会使您的Dictionary<>
操作非常慢 - 基本上,Dictionary<>
现在必须搜索其所有条目才能找到正确的密钥,就像它是一个简单的列表一样。
您可能希望KeyValuePair<>
的两个KeyValuePair<>
对象是相同的,如果它们的键和它们的值依次相等。您可以这样实现:
public class KeyValuePair<K, V>
{
private K m_key;
private V m_value;
// [...] existing implementation left out
public override bool Equals(object obj)
{
KeyValuePair<K, V> other = obj as KeyValuePair<K, V>;
if(other == null)
return false;
return object.Equals(this.m_key, other.m_key) && object.Equals(this.m_value, other.m_value);
}
public override int GetHashCode()
{
int hashCode = 0;
if(m_key != null)
hashCode += m_key.GetHashCode();
if(m_value != null)
hashCode = hashCode * 31 + m_value.GetHashCode();
return hashCode;
}
}
请注意,这要求K和V以对您有意义的方式实施Equals()
和GetHashCode()
。
答案 2 :(得分:0)
发布详细示例:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
public override bool Equals(object obj)
{
return this.Id==((Foo)obj).Id
&& this.Name==((Foo)obj).Name;
}
public override int GetHashCode()
{
return Id.GetHashCode() + Name.ToLower().GetHashCode();
}
}
public class Bar
{
public int SomeOtherId { get; set; }
public string SomeOtherName { get; set; }
public override bool Equals(object obj)
{
return this.SomeOtherId == ((Bar)obj).SomeOtherId
&& this.SomeOtherName == ((Bar)obj).SomeOtherName;
}
public override int GetHashCode()
{
return SomeOtherId.GetHashCode() + SomeOtherName.ToLower().GetHashCode();
}
}
//Usage
var dict = new Dictionary<KeyValuePair<Foo, Bar>, float>();
dict.Add(new KeyValuePair<Foo, Bar>(new Foo { Id = 1, Name = "Foo" }, new Bar {SomeOtherId = 1, SomeOtherName = "Bar"}), 10);
Console.WriteLine(dict[new KeyValuePair<Foo, Bar>(new Foo { Id = 1, Name = "Foo" }, new Bar {SomeOtherId = 1, SomeOtherName = "Bar"})]);
答案是根据帖子的标题。但是,如果字典中有相同的键(尽管是不同的引用),它仍然不会跟随,因为当您尝试添加此类键时(在应用Equals
&amp; GetHashCode
之后),它不允许你插入这些相同的键。