我有这堂课:
class A {
string name;
string code;
}
示例:
A1: name="blabla", code="kuku"
A2: name="blabla", code=null
A3: name=null, code="kuku"
Dictionary<A, string> d=new Dictionary<A, string>();
d[A1]="aaa";
d[A2]="bbb"
results: d[A1]="bbb";
d[A1]="aaa";
d[A3]="bbb"
results: d[A1]="bbb";
d[A2]="aaa";
d[A3]="bbb"
results: d[A2]="aaa"; d[A3]="bbb";
有没有办法将A类实现为字典的键?
答案 0 :(得分:3)
你不能。
Equals
/ GetHashCode
实现必须形成[等价关系] - 它们必须满足以下属性:
您的定义不具有传递性; (a, b)
== (b, c)
和(b, c)
== (c, d)
但(a, b)
!= (c, d)
。
答案 1 :(得分:3)
不是实现GetHashCode
,更好的选择是实现自己的IEqualityComparer<A>
并将其传递给字典的构造函数。话虽这么说,你的等价规则没有意义。编程中的等价性必须遵循标准的代数等价规则。
在您的情况下,您有三个被视为“相等”的对象,这似乎是基于两个属性中的一个是否相等。但是,这种方法不能提供所需的传递平等。由于名称,#1 =#2。因为代码,#1 =#3。但是,等式和等价要求如果a = b且b = c,则a = c。在您的情况下,将#2与#3进行比较显示没有等价或相等,因为它们没有匹配的属性,即使它们都等于#1。
简短版本是您的等同/等效规则不能用于任何基于密钥的存储库,例如Dictionary
。
如果您确信这是正确的方法,那么这将是您正在寻找的,,但这不会表现得一致。使用这种伪等价,没有什么能够始终如一。
class AEqualityComparer : IEqualityComparer<A>
{
public bool Equals(A x, A y)
{
return x == y || x.name == y.name || x.code == y.code;
}
public int GetHashCode(A x)
{
return -1; // impossible to compute; will negatively impact performance
}
}
...
Dictionary<A, string> dict = new Dictionary<A, string>(new AEqualityComparer());
然而,打破这个很容易:
dict[A1] = "foo";
dict[A2] = "bar";
// dict[A1] is now "bar", as expected
dict[A3] = "baz";
此处,dict[A1]
是"baz"
,正如所料。但是,dict[A2]
也是 "baz"
,即使A2
根据这些规则不等于A3
。这是因为使用的原始对象是A1
,它等于两者。
答案 2 :(得分:1)
回答您编辑过的问题:
制作两个不同的字典词典(一个用于名称,一个用于代码),并搜索您有值的字典。