2008-09-09 6 views
14

क्या GetHashCode() की वापसी मान लगातार मानी जाती है कि एक ही स्ट्रिंग मान का उपयोग किया जा रहा है? (सी #/एएसपी.नेट)क्या मैं गेटहाशकोड() के मानों पर लगातार निर्भर रह सकता हूं?

मैंने आज अपने सर्वर को एक सर्वर पर अपलोड किया और मुझे आश्चर्य हुआ कि मुझे कुछ डेटा दोबारा जोड़ना पड़ा क्योंकि मेरा सर्वर (win2008 64-bit) मेरे डेस्कटॉप कंप्यूटर की तुलना में अलग-अलग मान लौटा रहा था।

उत्तर

29

यदि मुझे गलत नहीं है, तो GetHashCode समान मान दिया जाता है, लेकिन यह ढांचे के विभिन्न संस्करणों में लगातार होने की गारंटी नहीं है।

String.GetHashCode पर MSDN डॉक्स() से:

GetHashCode के व्यवहार इसके कार्यान्वयन, जो दूसरे के लिए आम भाषा क्रम के एक संस्करण से बदल सकता है पर निर्भर है। GetHashCode के प्रदर्शन में सुधार करने का एक कारण यह हो सकता है।

+1

निष्कर्ष: 'GetHashCode() 'के परिणाम को जारी या प्रसारित न करें। इसे केवल अपने इच्छित उद्देश्य के लिए उपयोग करें: हैश टेबल के उपयोग को सुविधाजनक बनाने के लिए। –

0

मुझे आश्चर्य है कि अगर वहाँ 32-बिट और 64-बिट ऑपरेटिंग सिस्टम के बीच मतभेद हैं, क्योंकि मैं कुछ दोनों अपने सर्वर और घर के कंप्यूटर नेट

का एक ही संस्करण चला रहे हैं मैं हमेशा के थके हुए था हूँ GetHashCode() का उपयोग करके, मेरे लिए अपने स्वयं के हैश एल्गोरिदम की भूमिका निभाना एक अच्छा विचार हो सकता है। खैर कम से कम मैं इसके कारण एक त्वरित पुनः सूचकांक .aspx पेज लिखना समाप्त कर दिया।

0

क्या आप अपने डेस्कटॉप के रूप में Win2008 x86 चला रहे हैं? क्योंकि Win2008 में संस्करण 2.0.50727.1434 शामिल है, जो कि Vista RTM में 2.0 का एक अद्यतन संस्करण शामिल है।

0

नहीं अपने प्रश्न है, जो जोनास अच्छी तरह से उत्तर दिया है के लिए एक सीधा जवाब है, लेकिन इस सहायता के हो सकता है अगर आप हैश

हमारे परीक्षणों, क्या आप hashcodes साथ की आवश्यकता होती है पर निर्भर करता है से में समानता परीक्षण के बारे में चिंतित हैं, सी # में, हैशकोड को समानता संचालन के लिए अद्वितीय होने की आवश्यकता नहीं है। उदाहरण के तौर पर, निम्नलिखित पर विचार करें:

हमें बराबर ऑपरेटर को अधिभारित करने की आवश्यकता थी, और इसलिए हमारे ऑब्जेक्ट्स के गेटहाशकोड फ़ंक्शन के रूप में वे अस्थिर और स्टेटलेस बन गए थे, और डेटा से सीधे सोर्सिंग कर रहे थे, इसलिए एक ही स्थान पर यह एप्लिकेशन यह सुनिश्चित करने के लिए आवश्यक था कि किसी ऑब्जेक्ट को अन्य ऑब्जेक्ट के बराबर के रूप में देखा जा सके, यदि उसे उसी डेटा से सोर्स किया गया था, न कि यह वही संदर्भ था। हमारे अद्वितीय डेटा पहचानकर्ता गिड्स हैं।

बराबर ऑपरेटर को पूरा करने में आसान था क्योंकि हमने अभी रिकॉर्ड के ग्रिड (शून्य के लिए जांच के बाद) पर जांच की थी।

असहज रूप से हैशकोड डेटा आकार (एक int होने) ऑपरेटिंग सिस्टम पर निर्भर करता है, और हमारे 32 बिट सिस्टम पर, हैशकोड 32 बिट होगा। गणितीय रूप से, जब हम GetHashCode फ़ंक्शन को ओवरराइड करते हैं, तो 32 बिट से अधिक की एक ग्रिड से एक अद्वितीय हैशकोड उत्पन्न करना असंभव है (इसे विपरीत से देखें, आप 32 बिट पूर्णांक को ग्रिड में कैसे अनुवाद करेंगे?)।

हमने तब कुछ परीक्षण किए जहां हमने ग्रिड को एक स्ट्रिंग के रूप में लिया और ग्रिड के हैशकोड को वापस कर दिया, जो लगभग हमेशा हमारे परीक्षणों में एक अद्वितीय पहचानकर्ता देता है, लेकिन हमेशा नहीं।

हमने ऑब्जेक्ट किया है, जब कोई ऑब्जेक्ट हैश संग्रह संग्रह ऑब्जेक्ट (एक हैशटेबल, एक शब्दकोश इत्यादि) में है, जब 2 ऑब्जेक्ट अद्वितीय नहीं हैं लेकिन उनके हैशकोड हैं, हैशकोड केवल पहले विकल्प लुकअप के रूप में उपयोग किया जाता है, यदि गैर-अद्वितीय हैश कोड का उपयोग किया जा रहा है, समानता ऑपरेटर हमेशा समानता की पहचान करने के लिए गिरावट के रूप में उपयोग किया जाता है।

जैसा कि मैंने कहा था कि यह आपकी स्थिति के लिए प्रासंगिक हो सकता है या नहीं, लेकिन यदि यह एक आसान युक्ति है।

कुंजी:: वस्तु एक (हैशकोड 1), मूल्य वस्तु A1

कुंजी: ऑब्जेक्ट बी (हैशकोड 1), मूल्य वस्तु

अद्यतन

प्रदर्शित करने के लिए, हम एक Hashtable है बी 1

कुंजी: ऑब्जेक्ट सी (हैशकोड 1), मूल्य वस्तु सी 1

कुंजी: ऑब्जेक्ट डी (हैशकोड 2), मूल्य ओब अस्वीकृत डी 1

कुंजी: ऑब्जेक्ट ई (हैशकोड 3), मूल्य वस्तु E1

जब मैं वस्तु एक के प्रमुख के साथ वस्तु के लिए hashtable फोन, वस्तु A1 2 चरणों के बाद वापस कर दी जाएगी, के लिए एक कॉल हैशकोड 1, फिर कुंजी ऑब्जेक्ट पर एक समानता जांच है क्योंकि हैशकोड 1

जब मैं ऑब्जेक्ट डी की कुंजी के साथ ऑब्जेक्ट के लिए हैशटेबल को कॉल करता हूं, तो ऑब्जेक्ट डी 1 1 चरण के बाद वापस कर दिया जाएगा , हैश लुकअप

0

हमने क्या देखा, हालांकि वस्तु टुकड़ों में बंटी संग्रह वस्तु (एक hashtable, एक शब्दकोश आदि), में है जब 2 वस्तुओं अद्वितीय नहीं हैं, लेकिन उनके hashcodes, कर रहे हैं hashCode केवल देखते हैं यदि गैर-अद्वितीय, एक पहला विकल्प देखने के रूप में प्रयोग किया जाता है हैश कोड का उपयोग किया जा रहा है, समानता ऑपरेटर हमेशा पर समानता की पहचान के रूप में उपयोग के रूप में उपयोग किया जाता है।

इस तरह हैश लुकअप काम करता है, है ना? प्रत्येक बाल्टी में एक ही हैश कोड वाले आइटमों की एक सूची होती है।

इसलिए इन शर्तों के तहत सही आइटम को खोजने के लिए मूल्य समानता तुलना का उपयोग करके एक रैखिक खोज होती है।

और यदि आपके हैशिंग कार्यान्वयन में अच्छा वितरण प्राप्त होता है, तो यह खोज आवश्यक नहीं है, यानी प्रति आइटम एक आइटम।

क्या मेरी समझ सही है?

+0

बेन, हमारे परीक्षण से, यह सच है। दूसरी समानता खोज केवल आवश्यकतानुसार चलती है। आप ==,! =, बराबर() और एक निश्चित ऑब्जेक्ट के GetHashCode को ओवरलोड करके स्वयं का परीक्षण कर सकते हैं। मैंने इसे बहुत रोचक पाया (लेकिन मैं एक गीक हूं :)) – johnc

+0

(जारी), इसलिए नॉन्यूनिक हैश कोड के प्रभाव पर दस्तक समानता जांच चलाने के लिए धीमी कार्यक्षमता होगी, लेकिन हमारी स्थिति में जहां नॉन्यूनिक मान बहुत दुर्लभ है, यह काफी हद तक महत्वहीन है – johnc

5

कार्यान्वयन ढांचे के संस्करण पर निर्भर है लेकिन यह architecture पर भी निर्भर करता है। String.GetHashCode() का कार्यान्वयन फ्रेमवर्क के x86 और x64 संस्करणों में भिन्न है, भले ही उनके पास समान संस्करण संख्या हो।

10

मुझे एक ऐसी ही समस्या थी जहां मैंने एक डेटाबेस तालिका भर दी जो स्ट्रिंग पर निर्भर था। गेटहाशकोड (सबसे अच्छा विचार नहीं) और जब मैंने सर्वर को अपग्रेड किया तो मैं x64 पर काम कर रहा था, मैंने देखा कि मैं जो मूल्य प्राप्त कर रहा था स्ट्रिंग।GetHashCode पहले से ही तालिका में क्या था के साथ असंगत थे। मेरा समाधान गेटहाशकोड के अपने संस्करण का उपयोग करना था जो x86 ढांचे पर स्ट्रिंग.गेटहाशकोड के समान मूल्य देता है।

यहाँ कोड है, मत भूलना "असुरक्षित कोड की अनुमति दें" के साथ संकलित करने के लिए:

/// <summary> 
    /// Similar to String.GetHashCode but returns the same as the x86 version of String.GetHashCode for x64 and x86 frameworks. 
    /// </summary> 
    /// <param name="s"></param> 
    /// <returns></returns> 
    public static unsafe int GetHashCode32(string s) 
    { 
     fixed (char* str = s.ToCharArray()) 
     { 
      char* chPtr = str; 
      int num = 0x15051505; 
      int num2 = num; 
      int* numPtr = (int*)chPtr; 
      for (int i = s.Length; i > 0; i -= 4) 
      { 
       num = (((num << 5) + num) + (num >> 0x1b))^numPtr[0]; 
       if (i <= 2) 
       { 
        break; 
       } 
       num2 = (((num2 << 5) + num2) + (num2 >> 0x1b))^numPtr[1]; 
       numPtr += 2; 
      } 
      return (num + (num2 * 0x5d588b65)); 
     } 
    } 
+1

मुझे एक ही समस्या थी और आपके संस्करण को एक सुरक्षित विधि में पोर्ट किया गया था। https://gist.github.com/gerriten/7542231#file-gethashcode32-net –

-1

मुझे कहना है कि ... आप उस पर भरोसा नहीं कर सकते। उदाहरण के लिए यदि मैं c1 के md5 हैश कोड के माध्यम से फ़ाइल 1 चलाता हूं और प्रतिलिपि एक ही फ़ाइल को एक नई निर्देशिका में पेस्ट करता हूं ... हैश कोड अलग-अलग होता है, यह भी वही फ़ाइल है। जाहिर है, यह वही .net संस्करण, वही सब कुछ है। एकमात्र चीज जो बदल गई वह पथ थी।

1
/// <summary> 
    /// Default implementation of string.GetHashCode is not consistent on different platforms (x32/x64 which is our case) and frameworks. 
    /// FNV-1a - (Fowler/Noll/Vo) is a fast, consistent, non-cryptographic hash algorithm with good dispersion. (see http://isthe.com/chongo/tech/comp/fnv/#FNV-1a) 
    /// </summary> 
    private static int GetFNV1aHashCode(string str) 
    { 
     if (str == null) 
      return 0; 
     var length = str.Length; 
     // original FNV-1a has 32 bit offset_basis = 2166136261 but length gives a bit better dispersion (2%) for our case where all the strings are equal length, for example: "3EC0FFFF01ECD9C4001B01E2A707" 
     int hash = length; 
     for (int i = 0; i != length; ++i) 
      hash = (hash^str[i]) * 16777619; 
     return hash; 
    } 

यह कार्यान्वयन पहले पोस्ट किए गए असुरक्षित से धीमा हो सकता है। लेकिन बहुत आसान और सुरक्षित है।

संबंधित मुद्दे

 संबंधित मुद्दे