2010-10-14 53 views
1

我遇到了以下代碼的一個奇怪的問題,下面的代碼假設在一次迭代後停止,但它只是繼續前進。但是,如果我刪除了最後一個「result_bytes = md5.ComputeHash(orig_bytes);」那麼它會工作。有沒有人以前面臨類似的問題?MD5哈希的怪異行爲

MD5 md5; 
      byte[] orig_bytes; 
      byte[] result_bytes; 
      Dictionary<byte[], string> hashes = new Dictionary<byte[], string>(); 

      string input = "NEW YORK"; 
      result_bytes = UnicodeEncoding.Default.GetBytes("HELLO"); 
while (!hashes.ContainsKey(result_bytes)) 
      { 
       md5 = new MD5CryptoServiceProvider(); 
       orig_bytes = UnicodeEncoding.Default.GetBytes(input); 
       result_bytes = md5.ComputeHash(orig_bytes); 

       hashes.Add(result_bytes, input); 
       Console.WriteLine(BitConverter.ToString(result_bytes)); 
       Console.WriteLine(hashes.ContainsKey(result_bytes)); 

       result_bytes = md5.ComputeHash(orig_bytes); 
      } 

回答

2

當您重新分配result_bytes在最後一行新的值,你有一個新的參考字節數組,這不等於一個集合中,因此hashes.ContainsKey返回false。

+0

感謝您的答覆,但他們都做同樣的thing result_bytes = md5.ComputeHash(orig_bytes);這只是我實際邏輯的一個快照,因爲我需要重新計算,但是奇怪的是爲什麼同一個命令會給出不同的結果呢? orig_bytes根本沒有改變,斷點顯示字節[]內容相同 – cherhan 2010-10-14 06:42:30

+1

雖然兩個數組中的字節相同,但是每次調用ComputeHash時,都會得到一個帶有不同引用和不同GetHashCode()值的新字節數組, Dictionary用它來比較它的鍵。 (byte []是一個引用類型,每個新對象在默認情況下被認爲是不同的,不管內容是什麼) – user472157 2010-10-14 06:46:17

2

你假設字節數組覆蓋EqualsGetHashCode比較是否相等:它們不是。他們只是使用默認的身份測試 - 所以最後沒有額外的分配,你只是檢查你剛剛添加的確切的關鍵對象是否仍然在字典中 - 當然是這樣。

其中一種方法是存儲散列的可逆字符串表示(例如使用base64),而不是散列本身。或者編寫你自己的IEqualityComparer<byte[]>實現並將其傳遞給Dictionary構造函數,以便它使用該實現來查找字節數組的哈希碼並將它們相互比較。

簡而言之:這有沒有關係MD5,什麼都做的事實,

Console.WriteLine(new byte[0].Equals(new byte[0])); 

將打印假:)

+0

我也對下面的線程做了類似的評論。這是我的實際邏輯的快照,但我的問題是,如果orig_bytes沒有改變,爲什麼result_bytes會改變?如果result_bytes沒有改變(我很確定,除非我對MD5有錯誤的理解),那麼爲什麼contains_key失敗? – cherhan 2010-10-14 06:45:11

+0

@cherhan:我想我已經很清楚地解釋了這一點......你正在重新計算MD5哈希值,所以你最終會得到一個新的數組。它包含與前一個數組相同的數據,但它不會在Dictionary /依賴的Equals/GetHashCode下相等。看看我的兩個空數組的示例 - 它們顯然具有相同的數據(無!),但「Equals」返回false。 – 2010-10-14 06:51:34