我有一个简单的例子:
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Dictionary<MyKey, string> data = new Dictionary<MyKey, string>();
data.Add(new MyKey("1", "A"), "value 1A");
data.Add(new MyKey("2", "A"), "value 2A");
data.Add(new MyKey("1", "Z"), "value 1Z");
data.Add(new MyKey("3", "A"), "value 3A");
string myValue;
if (data.TryGetValue(new MyKey("1", "A"), out myValue))
Console.WriteLine("I have found it: {0}", myValue );
}
}
public struct MyKey
{
private string row;
private string col;
public string Row { get { return row; } set { row = value; } }
public string Column { get { return col; } set { col = value; } }
public MyKey(string r, string c)
{
row = r;
col = c;
}
}
}
这很好用。但是,如果我以这种方式通过MyKey类更改MyKey结构:
public class MyKey
然后方法TryGetValue
找不到任何密钥,尽管密钥已经存在。
我确信我错过了一些明显的东西,但我不知道是什么。
有什么想法吗?
由于
(请参阅已接受的解决方案以获得更好的GetHashCode解析)
我已经像这样重新定义了MyKey类,现在一切正常:
public class MyKey
{
private string row;
private string col;
public string Row { get { return row; } set { row = value; } }
public string Column { get { return col; } set { col = value; } }
public MyKey(string r, string c)
{
row = r;
col = c;
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is MyKey)) return false;
return ((MyKey)obj).Row == this.Row && ((MyKey)obj).Column == this.Column;
}
public override int GetHashCode()
{
return (this.Row + this.Column).GetHashCode();
}
}
感谢所有人的回答。
答案 0 :(得分:6)
您需要覆盖课程Equals()
中的GetHashCode()
和MyKey
也许是这样的:
<强> GetHashCode()方法强>
public override int GetHashCode()
{
return GetHashCodeInternal(Row.GetHashCode(),Column.GetHashCode());
}
//this function should be move so you can reuse it
private static int GetHashCodeInternal(int key1, int key2)
{
unchecked
{
//Seed
var num = 0x7e53a269;
//Key 1
num = (-1521134295 * num) + key1;
num += (num << 10);
num ^= (num >> 6);
//Key 2
num = ((-1521134295 * num) + key2);
num += (num << 10);
num ^= (num >> 6);
return num;
}
}
<强>等于强>
public override bool Equals(object obj)
{
if (obj == null)
return false;
MyKey p = obj as MyKey;
if (p == null)
return false;
// Return true if the fields match:
return (Row == p.Row) && (Column == p.Column);
}
答案 1 :(得分:4)
因为默认情况下使用参考比较来比较类。
如果比较两个对象,你正在做一个object.ReferenceEquals(obj1,obj2)
如果比较两个结构,则进行值比较(例如比较两个整数时)。
如果你想比较两个MyKey对象,你需要实现自己的Equals
和GetHashCode
方法,它将被字典自动使用。
答案 2 :(得分:3)
Struct是值类型而Class是引用类型,因此当你使用struct时,它内部的所有值都会被比较,但是当你使用class时,只会检查对象引用。
您可以通过覆盖Equals()
方法更改某些类的行为。如果需要,您还可以覆盖==
运算符。请参阅Guidelines for Overloading Equals() and Operator == (C# Programming Guide)上的示例。
编辑:
您的Equals()
方法应如下所示:
public override bool Equals(System.Object obj)
{
MyKey p = obj as MyKey;
if ((System.Object)p == null)
{
return false;
}
// Return true if the fields match:
return (row == p.row) && (col == p.col);
}