객체의 필드를 일반 사전 키로 사용
객체를의 키로 사용하려면 Dictionary
특정 방식으로 객체를 비교하기 위해 어떤 방법을 재정의해야합니까?
속성이있는 클래스가 있다고 가정 해보십시오.
class Foo {
public string Name { get; set; }
public int FooID { get; set; }
// elided
}
그리고 나는 :
Dictionary<Foo, List<Stuff>>
Foo
같은 개체를 FooID
같은 그룹으로 간주하고 싶습니다 . Foo
클래스 에서 어떤 메서드를 재정의해야 합니까?
요약하면 : Stuff
객체를 Foo
객체 별로 그룹화하여 목록 으로 분류하려고 합니다. Stuff
객체는 FooID
카테고리에 링크 할 수 있습니다.
기본적으로 두 가지 중요한 방법은 GetHashCode()
및 Equals()
입니다. 두 가지가 같으면 ( Equals()
참을 반환) 동일한 해시 코드를 가져야합니다. 예를 들어 "FooID를 반환합니다"; 는 AS 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
이미 지원하는 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가 동일한 지 비교하기 위해 동일합니다.
Make sure to calculate good hash codes (avoid many equal Foo objects having the same hashcode), but make sure two equals Foos have the same hash code. You might want to start with the Equals-Method and then (in GetHashCode()) xor the hash code of every member you compare in 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();
}
}
I had the same problem. I can now use any object I've tried as a key due to overriding Equals and GetHashCode.
Here is a class that I built with methods to use inside of the overrides of Equals(object obj) and GetHashCode(). I decided to use generics and a hashing algorithm that should be able to cover most objects. Please let me know if you see anything here that doesn't work for some types of object and you have a way to improve it.
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;
}
}
Here is how it's used in a class:
public override bool Equals(object obj)
{
return new Equality<ClassName>().Equals(this, obj);
}
public override int GetHashCode()
{
unchecked
{
return new Equality<ClassName>().GetHashCode(this);
}
}
What about Hashtable
class!
Hashtable oMyDic = new Hashtable();
Object oAnyKeyObject = null;
Object oAnyValueObject = null;
oMyDic.Add(oAnyKeyObject, oAnyValueObject);
foreach (DictionaryEntry de in oMyDic)
{
// Do your job
}
In above way, you can use any object (your class object) as a generic Dictionary key :)
참고URL : https://stackoverflow.com/questions/634826/using-the-field-of-an-object-as-a-generic-dictionary-key
'program story' 카테고리의 다른 글
힘내 : 가져 오기 전용 리모컨을 설정 하시겠습니까? (0) | 2020.07.27 |
---|---|
matplotlib의 세로 및 가로 선 (0) | 2020.07.27 |
C ++ 11에서 COW std :: string 구현의 적법성 (0) | 2020.07.27 |
Android 5.0 (Lollipop) 용으로 제시된 새로운 SD 카드 액세스 API를 사용하는 방법은 무엇입니까? (0) | 2020.07.27 |
자바 스크립트를 통해 버튼 클릭시 태그의 (0) | 2020.07.27 |