2016-01-06 112 views
1

我試圖使用GetHashCode()值來確定一個對象在通過ASP.NET MVC應用程序中的ajax調用進行驗證後是否發生了更改。但是,我注意到這並不奏效,因爲在驗證期間返回時的哈希碼值與在驗證請求之後從另一個請求中的模型綁定重新創建對象時生成的哈希碼不同。我能夠通過創建一個SHA哈希來解決這個問題,但我很好奇我爲什麼看到這種行爲。GetHashCode()爲相同的對象值返回不同的值

我知道從GetHashCode()生成的哈希代碼不應該被持久化,並且可能在不同的平臺上隨着時間的推移而不同。我認爲,當我第一次提出這個想法時,這段時間足夠短,因爲這兩個調用是以毫秒爲單位進行的,而且在調試時,我確認模型包含完全相同的值,但仍生成不同的哈希代碼。

我很好奇爲什麼會出現這種行爲。爲什麼會發生這種情況,即使這是應用程序的單一運行,儘管是一個Web應用程序?這是否與ASP.NET生命週期有關?

在這裏需要的情況下,是我用的是類& GetHashCode的實現:

class DispositionSubmission 
{ 
    [Display(Name = "Client")] 
    [Required(AllowEmptyStrings = false, ErrorMessage = "Client is required.")] 
    public string ClientId { get; set; } 
    public string Carrier { get; set; } 
    public Dictionary<string, string> DispositionInfo { get; set; } 
    public DispositionType Type { get; set; } //int based enum 

... 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      int hash = (int)15485863; 
      int bigPrime = (int)15485867; 

      hash = hash * bigPrime^ClientId.GetHashCode(); 
      hash = hash * bigPrime^(Carrier ?? "").GetHashCode(); 
      hash = hash * bigPrime^DispositionInfo.GetHashCode(); 
      hash = hash * bigPrime^Type.GetHashCode(); 

      return hash; 
     } 
    } 
} 

回答

4

DispositionInfo不具有覆蓋GetHashCode()一個類型。兩個具有相同對象的相同字典將具有不同的哈希碼。

您需要將GetHashCode()調整爲不包含字典或使字典中的每個鍵和值的哈希代碼更加複雜,並將其添加。

+0

啊!這就說得通了! * Smacks頭對着辦公桌* – JNYRanger

+0

我會更傾向於排除字典,GetHashCode應該是一個快速返回的函數,如果大的話可能會很慢,通過整個字典。 –

+0

它很少會有超過20個鍵值對,但我需要包含它,因爲我使用它來確保沒有任何變化(包括字典中的鍵值對)是使用哈希碼的目的。對它進行序列化並生成一個SHA-1哈希值就是個訣竅。不是性能最快的方法,但速度足以滿足其使用目的。 – JNYRanger

1

GetHashCode將爲完全相同的對象返回相同的結果。如果對象已被重新分配,則所有字段中的值是否相同並不重要,您將得到不同的結果。這是因爲你真正使用的是Object.GetHashCode(),無論如何它對其他領域一無所知。

此行爲非常重要,因爲如果您使用散列作爲引用對象的方式,更改其任何值都將導致無法再次引用。

如果您想要具有相同字段的對象具有相同散列碼的行爲,則需要自行實施。

編輯:澄清:DispositionInfo,字典,具體表現出這種行爲。其他字段沒有,因爲它們被設計爲不可變的(字符串,整型等)。考慮以不同的方式獲取散列,或者使用繼承自Dictionary<string, string>的自定義類來覆蓋GetHashCode

+0

我提到的不正確倍率的全部內容。他指的編輯前的響應。 – SaxxonPike

+0

@SaxxonPike看見你固定它,刪除了我的評論/ downvote – JNYRanger