如果我想使用对象作为Dictionary
的键,我需要重写哪些方法才能使它们以特定的方式进行比较?
假设我有一个a类,它有属性:
class Foo {
public string Name { get; set; }
public int FooID { get; set; }
// elided
}
我想创建一个:
Dictionary<Foo, List<Stuff>>
我希望具有相同FooID
的Foo
对象被视为同一组。我需要在Foo
类中覆盖哪些方法?
总而言之:我想将Stuff
对象分类到列表中,按Foo
对象分组。Stuff
对象将有一个FooID
将它们链接到它们的类别。
发布于 2009-03-11 14:49:16
默认情况下,两个重要的方法是GetHashCode()
和Equals()
。重要的是,如果两件事相等(Equals()
返回true),它们具有相同的哈希码。例如,如果您希望将其作为匹配项,则可以“返回FooID;”作为GetHashCode()
。您也可以实现IEquatable<Foo>
,但这是可选的:
class Foo : IEquatable<Foo> {
public string Name { get; set;}
public int FooID {get; set;}
public override int GetHashCode() {
return FooID;
}
public override bool Equals(object obj) {
return Equals(obj as Foo);
}
public bool Equals(Foo obj) {
return obj != null && obj.FooID == this.FooID;
}
}
最后,另一种选择是提供一个IEqualityComparer<T>
来做同样的事情。
发布于 2009-03-11 15:27:33
因为您希望FooID
作为组的标识符,所以应该使用它作为字典中的键,而不是Foo对象:
Dictionary<int, List<Stuff>>
如果要使用Foo
对象作为键,则只需将GetHashCode
和Equals
方法实现为只考虑FooID
属性。对于Dictionary
而言,Name
属性将是一个沉重的负担,因此您只需使用Foo
作为int
的包装器。
因此,最好直接使用FooID
值,这样就不必实现任何东西,因为Dictionary
已经支持使用int
作为键。
编辑:
如果您无论如何都想使用Foo
类作为键,那么IEqualityComparer<Foo>
很容易实现:
public class FooEqualityComparer : IEqualityComparer<Foo> {
public int GetHashCode(Foo foo) { return foo.FooID.GetHashCode(); }
public bool Equals(Foo foo1, Foo foo2) { return foo1.FooID == foo2.FooID; }
}
用法:
Dictionary<Foo, List<Stuff>> dict = new Dictionary<Foo, List<Stuff>>(new FooEqualityComparer());
发布于 2009-03-11 14:48:58
对于Foo,您需要重写object.GetHashCode()和object.Equals()
字典将调用GetHashCode()来计算每个值的散列桶,并使用等于来比较两个Foo是否相同。
确保计算出良好的散列码(避免许多相等的Foo对象具有相同的散列码),但确保两个equals Foo具有相同的散列码。您可能希望从Equals-Method开始,然后(在GetHashCode()中) xor您在Equals中比较的每个成员的散列代码。
public class Foo {
public string A;
public string B;
override bool Equals(object other) {
var otherFoo = other as Foo;
if (otherFoo == null)
return false;
return A==otherFoo.A && B ==otherFoo.B;
}
override int GetHashCode() {
return 17 * A.GetHashCode() + B.GetHashCode();
}
}
https://stackoverflow.com/questions/634826
复制相似问题