我有一个产品类,
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){
}
答案 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;
}
}
}