Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实施IEqualityComparer<;T>;关于C中具有两个属性的对象#_C#_Linq_Distinct_Iequalitycomparer - Fatal编程技术网

C# 实施IEqualityComparer<;T>;关于C中具有两个属性的对象#

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

我有一个例子,我需要在distinct上获取一组项目,但我的源是一组具有两个属性的对象,如下所示:

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;
        }
    }