如何在实例上创建Hash?

时间:2014-09-03 08:10:14

标签: c# hash

我有一个产品类,

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string ModelNumber { get; set; }
    public string Sku { get; set; }
    public string Description { get; set; }
    public double Price { get; set; }
    public double NewPrice { get; set; }
}

我在数据库表中保存了这个类。但是我还需要在数据库表中保存每个对象的哈希值以进行更改跟踪。我正在寻找的是,

        var p1 = new Product{
            Id =2,
            Name = "1",
            ModelNumber = "4"
        };
        var p2 = new Product
        {
            Id = 2,
            Name = "1",
            ModelNumber = "4"
        }; 
        var hashOfp1 = Hash(p1);
        var hashOfp2 = Hash(p2);
        // This should return true because both objects have same values
        if(hashOfp1  == hashOfp2){
        }

3 个答案:

答案 0 :(得分:2)

这种事情的好处是:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string ModelNumber { get; set; }
    public string Sku { get; set; }
    public string Description { get; set; }
    public double Price { get; set; }
    public double NewPrice { get; set; }

    public override int GetHashCode()
    {
        return Id ^ (Name ?? "").GetHashCode() ^ (ModelNumber ?? "").GetHashCode() ^ (Sku ?? "").GetHashCode()^ (Description ?? "").GetHashCode() ^ Price.GetHashCode() ^ NewPrice.GetHashCode();
    }
}

这个想法是结合所有子属性的哈希...你可以选择你想要的任何组合,但是“xor”运算符是一个很好的选择,因为它可以防止你的哈希值向你添加新属性时hash(比如“&”或“+”运算符)

修改 根据要求,“倾向于某事”部分的快速而肮脏的解释:

我们假设您选择了A& B& C& D ...哈希值A,B,C等。 你添加到哈希的大多数属性,你有更多的机会拥有一个倾向于int.MaxValue(对应于11111111111111111111111111111111,二进制)的巨大哈希

与“+”相同......你的哈希值会变得越来越大,而不是使用全部的int值。

...一个好的哈希算法就是最大化为不同值设置不同哈希的机会。要做到这一点,你可以研究如何在现实生活中使用的值(可能是痛苦和过度杀伤),或者最大化你的哈希算法覆盖随机未知值的int值的范围。

答案 1 :(得分:2)

您应该覆盖基类GetHashCode()Object方法。 在此重写方法中,您可以基于Id或其他属性创建哈希代码。

您可以使用它,然后像:

var hashOfp1 = p1.GetHashCode();

答案 2 :(得分:2)

如果重写GetHashCode(),您还应该重写Equals(object)。代码由ReSharper提供

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string ModelNumber { get; set; }
    public string Sku { get; set; }
    public string Description { get; set; }
    public double Price { get; set; }
    public double NewPrice { get; set; }

    protected bool Equals(Product other)
    {
        return Id == other.Id && string.Equals(Name, other.Name) && 
            string.Equals(ModelNumber, other.ModelNumber) && 
            string.Equals(Sku, other.Sku) && string.Equals(Description, other.Description) && 
            Price.Equals(other.Price) && NewPrice.Equals(other.NewPrice);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
        {
            return false;
        }
        if (ReferenceEquals(this, obj))
        {
            return true;
        }
        if (obj.GetType() != this.GetType())
        {
            return false;
        }
        return Equals((Product) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            var hashCode = Id;
            hashCode = (hashCode*397) ^ (Name != null ? Name.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (ModelNumber != null ? ModelNumber.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (Sku != null ? Sku.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ (Description != null ? Description.GetHashCode() : 0);
            hashCode = (hashCode*397) ^ Price.GetHashCode();
            hashCode = (hashCode*397) ^ NewPrice.GetHashCode();
            return hashCode;
        }
    }
}