C# 实施IEqualityComparer<;T>;关于C中具有两个属性的对象#
我有一个例子,我需要在distinct上获取一组项目,但我的源是一组具有两个属性的对象,如下所示:C# 实施IEqualityComparer<;T>;关于C中具有两个属性的对象#,c#,linq,distinct,iequalitycomparer,C#,Linq,Distinct,Iequalitycomparer,我有一个例子,我需要在distinct上获取一组项目,但我的源是一组具有两个属性的对象,如下所示: public class SkillRequirement { public string Skill { get; set; } public string Requirement { get; set; } } 我尝试收集以下信息: SkillRequirementComparer sCom = new SkillRequirementComparer(); var dis
public class SkillRequirement
{
public string Skill { get; set; }
public string Requirement { get; set; }
}
我尝试收集以下信息:
SkillRequirementComparer sCom = new SkillRequirementComparer();
var distinct_list = source.Distinct(sCom);
为此,我尝试实现一个IEqualityComparer
,但在GetHashCode()
方法中我遇到了难题
比较器的类:
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)
{
//?????
}
}
公共类技能要求比较器:IEqualityComparer
{
公共布尔等于(技能要求x,技能要求y)
{
如果(x.Skill.Equals(y.Skill)&&x.Requirement.Equals(y.Requirement))
{
返回true;
}
其他的
{
返回false;
}
}
public int GetHashCode(SkillRequirement obj)
{
//?????
}
}
通常我只会在属性上使用
GetHashCode()
,但因为我在比较两个属性,所以我有点不知所措。我是做错了什么,还是遗漏了一些非常明显的东西?您可以通过以下方式实现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;
我想链接下面的堆栈溢出帖子,虽然这个问题已经得到了回答 GetHashCode- 此外,在上面的回答中,Tim Schmelter说
属性可以为null,您应该避免出现NullReferenceException
int hash = 17;
hash = hash * 23 + (obj.Skill ?? "").GetHashCode();
hash = hash * 23 + (obj.Requirement ?? "").GetHashCode();
return hash;
IEqualityComparer-
i足够-
等于-
(事实上,它最初来自Josh Bloch;)@TimSchmelter我猜他担心对象被放入散列容器后字段会发生变异。哇,谢谢!你知道它是怎么工作的吗?在…:^之前,我甚至从未遇到过
未选中的关键字@FelixWeir:GetHashCode
应该很快,并且不会产生太多冲突(对于不相等的对象,相等的hashcode)。请注意,对于具有相同哈希代码的每个对象,都会调用Equals
。因此,Equals
的实现方式必须保证它根据定义为两个相等的对象返回true
,反之亦然GetHashCode
应尽可能高效且相当准确地实现。因为检查溢出需要时间,所以在没有溢出危险的情况下使用未经检查的代码可能会提高性能。@FelixWeir:请注意,如果GetHashCode
为两个不同的对象返回相同的hashcode,则可以。你应该尽量减少那些“错误的哈希代码”,但这并没有什么错。这就是为什么等于
作为附加检查存在的原因。但是,两个相等的对象应始终返回相同的哈希代码。阅读:。使用从可变字段派生的GetHashCode()
时要小心!如果将对象放入哈希集合中,则更改其中一个字段-哎哟。我建议将其设置为不可变。属性的值最初来自数据库,其中列不允许为null,在将对象添加到源列表之前,还可以检查null或空字符串,因此不需要担心:^)
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;
}
}