2014-09-03 144 views
1

我有一個產品類,如何創建實例的哈希?

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){ 
     } 
+2

見基於對象屬性這個答案讓哈希碼:http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system -object-gethashcode – Smudge202 2014-09-03 08:14:25

回答

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

的想法是哈希結合所有子屬性...你可以選擇你希望的任何組合,但「異或」運算符是一個相當不錯的選擇,因爲它可以防止您的哈希值當你添加新的屬性,你的哈希值(如「&」或「+」操作符會)

編輯趨於東西快速的要求髒解釋爲「趨向的東西」的一部分,:

讓我們假設你選擇了一個&乙&ç& d ...哈希值A,B,C等 最多屬性您添加到你的哈希,更多的機會,你將不得不有一個巨大的哈希往往int.MaxValue(其對應於11111111111111111111111111111111,二進制)

同樣的事情與「+」...你的哈希會變得越來越大,而不是使用全部的int值。

...一個好的散列算法就是最大化不同值的散列的機會。要做到這一點,您可以研究值如何在現實生活中使用(可以是痛苦的和過度的),或者最大化散列算法覆蓋的隨機未知值的int值範圍。

+0

你可以解釋一下'因爲它可以防止你的散列傾向於爲你的散列添加新屬性的東西' – user960567 2014-09-03 08:26:07

+0

在這裏看到我的答案爲什麼使用XOR進行散列碼計算並不總是一個好的選擇: http://stackoverflow.com/a/19139500/106159 – 2014-09-03 08:26:17

+0

@MthetheWWatson沒有一貫好的答案。但xor更簡單,並且適用於大多數場景... – Olivier 2014-09-03 08:28:19

2

您應該重寫基類ObjectGetHashCode()方法。 在此重寫方法中,您可以根據Id或其他屬性創建哈希碼。

您可以使用它,然後想:

var hashOfp1 = p1.GetHashCode(); 
2

如果重寫GetHashCode(),你應該也重載Equals(對象)。 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; 
     } 
    } 
}