Answers:
默认情况下,两个重要方法是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>
相同的功能。
由于您希望FooID
成为组的标识符,因此应将其用作字典中的键而不是Foo对象:
Dictionary<int, List<Stuff>>
如果将Foo
对象用作键,则只需实现GetHashCode
and Equals
方法即可仅考虑该FooID
属性。该Name
属性将仅是Dictionary
所涉及的自重,因此您仅可以Foo
用作的包装int
。
因此,最好FooID
直接使用该值,然后不必执行任何操作,因为Dictionary
已经支持使用an 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());
对于Foo,您将需要覆盖object.GetHashCode()和object.Equals()
字典将调用GetHashCode()来为每个值计算一个哈希桶,并等于来比较两个Foo是否相同。
确保计算出良好的哈希码(避免使用相同的哈希码的多个相等的Foo对象),但请确保两个等于Foos的哈希码相同。您可能想从Equals-Method开始,然后(在GetHashCode()中)对您在Equals中比较的每个成员的哈希码进行xor处理。
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();
}
}
什么Hashtable
类的!
Hashtable oMyDic = new Hashtable();
Object oAnyKeyObject = null;
Object oAnyValueObject = null;
oMyDic.Add(oAnyKeyObject, oAnyValueObject);
foreach (DictionaryEntry de in oMyDic)
{
// Do your job
}
通过以上方法,您可以将任何对象(您的类对象)用作通用的Dictionary键:)
我有同样的问题。由于覆盖了Equals和GetHashCode,我现在可以将尝试使用的任何对象用作键。
这是我使用方法构建的类,该方法可在Equals(object obj)和GetHashCode()的重写内部使用。我决定使用泛型和哈希算法,该算法应该能够覆盖大多数对象。如果您在这里看到不适用于某些类型的对象的任何东西,并且有改进的方法,请告诉我。
public class Equality<T>
{
public int GetHashCode(T classInstance)
{
List<FieldInfo> fields = GetFields();
unchecked
{
int hash = 17;
foreach (FieldInfo field in fields)
{
hash = hash * 397 + field.GetValue(classInstance).GetHashCode();
}
return hash;
}
}
public bool Equals(T classInstance, object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (classInstance.GetType() != obj.GetType())
{
return false;
}
return Equals(classInstance, (T)obj);
}
private bool Equals(T classInstance, T otherInstance)
{
List<FieldInfo> fields = GetFields();
foreach (var field in fields)
{
if (!field.GetValue(classInstance).Equals(field.GetValue(otherInstance)))
{
return false;
}
}
return true;
}
private List<FieldInfo> GetFields()
{
Type myType = typeof(T);
List<FieldInfo> fields = myType.GetTypeInfo().DeclaredFields.ToList();
return fields;
}
}
这是在类中的用法:
public override bool Equals(object obj)
{
return new Equality<ClassName>().Equals(this, obj);
}
public override int GetHashCode()
{
unchecked
{
return new Equality<ClassName>().GetHashCode(this);
}
}