Реализация IEqualityComparer <T> для объекта с двумя свойствами в С#
У меня есть случай, когда мне нужно захватить кучу элементов на разных, но мой источник представляет собой набор объектов с двумя свойствами, например:
public class SkillRequirement
{
public string Skill { get; set; }
public string Requirement { get; set; }
}
Я пытаюсь получить коллекцию следующим образом:
SkillRequirementComparer sCom = new SkillRequirementComparer();
var distinct_list = source.Distinct(sCom);
Я попытался реализовать IEqualityComparer<T>
для этого, но я упал в тупик по методу GetHashCode()
.
Класс для Comparer:
public class SkillRequirementComparer : IEqualityComparer<SkillRequirement>
{
public bool Equals(SkillRequirement x, SkillRequirement y)
{
if (x.Skill.Equals(y.Skill) && x.Requirement.Equals(y.Requirement))
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(SkillRequirement obj)
{
//?????
}
}
Обычно я просто использовал бы GetHashCode()
для свойства, но поскольку я сравниваю два свойства, я немного теряю, что делать. Я делаю что-то неправильно или пропуская что-то действительно очевидное?
Ответы
Ответ 1
Вы можете реализовать GetHashCode
следующим образом:
public int GetHashCode(SkillRequirement obj)
{
unchecked
{
int hash = 17;
hash = hash * 23 + obj.Skill.GetHashCode();
hash = hash * 23 + obj.Requirement.GetHashCode();
return hash;
}
}
изначально от J.Skeet
Если свойства могут быть null
, вы должны избегать NullReferenceException
, например:
int hash = 17;
hash = hash * 23 + (obj.Skill ?? "").GetHashCode();
hash = hash * 23 + (obj.Requirement ?? "").GetHashCode();
return hash;
Ответ 2
Я бы хотел связать следующие сообщения о переполнении стека, хотя вопрос уже ответил.
GetHashCode -
Почему важно переопределить GetHashCode, когда метод Equals переопределен?
Кроме того, в приведенном выше ответе Тим Шмельтер говорит the properties can be null you should avoid a NullReferenceException
int hash = 17;
hash = hash * 23 + (obj.Skill ?? "").GetHashCode();
hash = hash * 23 + (obj.Requirement ?? "").GetHashCode();
return hash;
IEqualityComparer -
IEquatable - Какая разница между IEquatable и просто переопределением Object.Equals()?
Равно - Рекомендации по перегрузке равных()
class TwoDPoint : System.Object
{
public readonly int x, y;
public TwoDPoint(int x, int y) //constructor
{
this.x = x;
this.y = y;
}
public override bool Equals(System.Object obj)
{
// If parameter is null return false.
if (obj == null)
{
return false;
}
// If parameter cannot be cast to Point return false.
TwoDPoint p = obj as TwoDPoint;
if ((System.Object)p == null)
{
return false;
}
// Return true if the fields match:
return (x == p.x) && (y == p.y);
}
public bool Equals(TwoDPoint p)
{
// If parameter is null return false:
if ((object)p == null)
{
return false;
}
// Return true if the fields match:
return (x == p.x) && (y == p.y);
}
public override int GetHashCode()
{
//return x ^ y;
}
}