Dan*_*ana 115 .net generics dictionary
如果我想使用对象作为a的键Dictionary
,我需要覆盖哪些方法以使它们以特定方式进行比较?
假设我有一个具有属性的类:
class Foo {
public string Name { get; set; }
public int FooID { get; set; }
// elided
}
Run Code Online (Sandbox Code Playgroud)
我想创建一个:
Dictionary<Foo, List<Stuff>>
Run Code Online (Sandbox Code Playgroud)
我希望Foo
具有相同对象的对象FooID
被视为同一组.我需要在Foo
课程中覆盖哪些方法?
总结一下:我想将Stuff
对象分类为按Foo
对象分组的列表.Stuff
对象将有一个FooID
将它们链接到他们的类别.
Mar*_*ell 145
默认情况下,两个重要的方法是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;
}
}
Run Code Online (Sandbox Code Playgroud)
最后,另一种选择是提供IEqualityComparer<T>
相同的功能.
Guf*_*ffa 31
如您所希望的那样FooID
是组的标识符,您应该将其用作字典中的键而不是Foo对象:
Dictionary<int, List<Stuff>>
Run Code Online (Sandbox Code Playgroud)
如果您将Foo
对象用作键,则只需实现GetHashCode
和Equals
方法以仅考虑该FooID
属性.Name
就Dictionary
所涉及的而言,该属性只是自重,所以你只需要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; }
}
Run Code Online (Sandbox Code Playgroud)
用法:
Dictionary<Foo, List<Stuff>> dict = new Dictionary<Foo, List<Stuff>>(new FooEqualityComparer());
Run Code Online (Sandbox Code Playgroud)
对于Foo,您需要覆盖object.GetHashCode()和object.Equals()
字典将调用GetHashCode()来计算每个值的哈希桶,并使用Equals来比较两个Foo是否相同.
确保计算好的哈希码(避免许多具有相同哈希码的相等Foo对象),但要确保两个等于Foos具有相同的哈希码.您可能希望从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();
}
}
Run Code Online (Sandbox Code Playgroud)