包含通用数组对象GetHash code覆盖 [英] GetHashCode override of object containing generic array

查看:97
本文介绍了包含通用数组对象GetHash code覆盖的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含以下两个属性的类:

 公众诠释标识{搞定;私人集; }
大众T []值{搞定;私人集; }

我已 IEquatable< T> 并重写了的Object.Equals 是这样的:

 公共覆盖布尔等于(obj对象)
{
    返回的equals(OBJ作为SimpleTableRow< T>);
}公共布尔等于(SimpleTableRow< T>其他)
{
    //检查是否为空
    如果(的ReferenceEquals(其他,NULL))
        返回false;    //检查相同的参考
    如果(的ReferenceEquals(这一点,其他))
        返回true;    //检查相同的ID和相同的价值观
    返回标识== other.Id&放大器;&安培; Values​​.SequenceEqual(other.Values​​);
}

有覆盖当的Object.Equals 我还必须重写 GetHash code 当然。但是,code我应该实现?如何创建一个散列code OUT通用阵列?我如何使用编号整数结合起来呢?

 公共覆盖INT GetHash code()
{
    返回//什么?
}


解决方案

由于该线程中提出的问题,我张贴展示,如果你弄错了......主要是发​​生什么事,另一个回答,你不能使用数组的 GetHash code();正确的行为是,当你运行它...切换的意见来解决它没有任何警告的印刷:

 使用系统;
使用System.Collections.Generic;
使用System.Linq的;
静态类节目
{
    静态无效的主要()
    {
        //第一和第二逻辑上都相同
        SimpleTableRow< INT>第一=新SimpleTableRow&所述; INT>(1,2,3,4,5,6),
            第二=新SimpleTableRow&所述; INT>(1,2,3,4,5,6);        如果(first.Equals(二)及和放大器;!first.GetHash code()= second.GetHash code())
        {//证明平等相待,但GetHash code()不同意
            Console.WriteLine(我们有一个问题);
        }
        HashSet的< SimpleTableRow< INT>>设置=新的HashSet< SimpleTableRow< INT>>();
        set.Add(第一);
        set.Add(第二);
        //这混淆任何使用散列算法
        如果(set.Count = 1!)Console.WriteLine(是的,非常糟糕确实);
    }
}
类SimpleTableRow< T> :IEquatable< SimpleTableRow< T>>
{    公共SimpleTableRow(INT ID,则params T []值){
        this.Id = ID;
        this.Values​​ =值;
    }
    公众诠释标识{搞定;私人集; }
    大众T []值{搞定;私人集; }    公共覆盖INT GetHash code()//错误
    {
        返回Id.GetHash code()^ Values​​.GetHash code();
    }
    / *
    公共覆盖INT GetHash code()//右
    {
        INT哈希= ID;
        如果(值!= NULL)
        {
            哈希=(散* 17)+ Values​​.Length;
            的foreach(中值T(T))
            {
                哈希* = 17;
                如果(T!= NULL)哈希散列= + t.GetHash code();
            }
        }
        返回哈希;
    }
    * /
    公众覆盖布尔等于(obj对象)
    {
        返回的equals(OBJ作为SimpleTableRow< T>);
    }
    公共布尔等于(SimpleTableRow< T>其他)
    {
        //检查是否为空
        如果(的ReferenceEquals(其他,NULL))
            返回false;        //检查相同的参考
        如果(的ReferenceEquals(这一点,其他))
            返回true;        //检查相同的ID和相同的价值观
        返回标识== other.Id&放大器;&安培; Values​​.SequenceEqual(other.Values​​);
    }
}

I have a class that contains the following two properties:

public int Id      { get; private set; }
public T[] Values  { get; private set; }

I have made it IEquatable<T> and overriden the object.Equals like this:

public override bool Equals(object obj)
{
    return Equals(obj as SimpleTableRow<T>);
}

public bool Equals(SimpleTableRow<T> other)
{
    // Check for null
    if(ReferenceEquals(other, null))
        return false;

    // Check for same reference
    if(ReferenceEquals(this, other))
        return true;

    // Check for same Id and same Values
    return Id == other.Id && Values.SequenceEqual(other.Values);
}

When having override object.Equals I must also override GetHashCode of course. But what code should I implement? How do I create a hashcode out of a generic array? And how do I combine it with the Id integer?

public override int GetHashCode()
{
    return // What?
}

解决方案

Because of the problems raised in this thread, I'm posting another reply showing what happens if you get it wrong... mainly, that you can't use the array's GetHashCode(); the correct behaviour is that no warnings are printed when you run it... switch the comments to fix it:

using System;
using System.Collections.Generic;
using System.Linq;
static class Program
{
    static void Main()
    {
        // first and second are logically equivalent
        SimpleTableRow<int> first = new SimpleTableRow<int>(1, 2, 3, 4, 5, 6),
            second = new SimpleTableRow<int>(1, 2, 3, 4, 5, 6);

        if (first.Equals(second) && first.GetHashCode() != second.GetHashCode())
        { // proven Equals, but GetHashCode() disagrees
            Console.WriteLine("We have a problem");
        }
        HashSet<SimpleTableRow<int>> set = new HashSet<SimpleTableRow<int>>();
        set.Add(first);
        set.Add(second);
        // which confuses anything that uses hash algorithms
        if (set.Count != 1) Console.WriteLine("Yup, very bad indeed");
    }
}
class SimpleTableRow<T> : IEquatable<SimpleTableRow<T>>
{

    public SimpleTableRow(int id, params T[] values) {
        this.Id = id;
        this.Values = values;
    }
    public int Id { get; private set; }
    public T[] Values { get; private set; }

    public override int GetHashCode() // wrong
    {
        return Id.GetHashCode() ^ Values.GetHashCode();
    }
    /*
    public override int GetHashCode() // right
    {
        int hash = Id;
        if (Values != null)
        {
            hash = (hash * 17) + Values.Length;
            foreach (T t in Values)
            {
                hash *= 17;
                if (t != null) hash = hash + t.GetHashCode();
            }
        }
        return hash;
    }
    */
    public override bool Equals(object obj)
    {
        return Equals(obj as SimpleTableRow<T>);
    }
    public bool Equals(SimpleTableRow<T> other)
    {
        // Check for null
        if (ReferenceEquals(other, null))
            return false;

        // Check for same reference
        if (ReferenceEquals(this, other))
            return true;

        // Check for same Id and same Values
        return Id == other.Id && Values.SequenceEqual(other.Values);
    }
}

这篇关于包含通用数组对象GetHash code覆盖的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆