2009-06-05 8 views
13

मेरे पास सी # में एक पता वर्ग है जो इस तरह दिखता है:क्या मुझे अपने स्ट्रिंग फ़ील्ड के एक हैश कोड के रूप में एक संयोजन का उपयोग करना चाहिए?

public class Address 
{    
    public string StreetAddress { get; set; } 
    public string RuralRoute { get; set; } 
    public string City { get; set; } 
    public string Province { get; set; } 
    public string Country { get; set; } 
    public string PostalCode { get; set; } 
} 

मैं समानता लागू कर रहा हूं और इसलिए मुझे हैश कोड को ओवरराइड करने की आवश्यकता है। सबसे पहले मैं ईजे से हैशकोड फॉर्मूला का उपयोग करने जा रहा था लेकिन फिर मैंने सोचा: ये सभी स्ट्रिंग फ़ील्ड हैं, क्या मैं सिर्फ एक स्ट्रिंगबिल्डर का उपयोग करके उन्हें संयोजित करने और उस स्ट्रिंग से हैश कोड वापस नहीं कर सकता?

यह है:

var str = new StringBuilder(); 
str.Append(StreetAddress) 
    .Append(RuralRoute) 
    ... 

return str.ToString().GetHashCode(); 

इस के फायदे/नुकसान क्या हैं? मुझे ऐसा क्यों नहीं करना चाहिए?

+1

आपके विचार के लिए: भी नहीं http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-systemobjectgethashcode – lance

उत्तर

14

मैं बस इस आधार पर ऐसा करने से बचूंगा कि यह तारों का एक समूह निर्बाध रूप से बनाता है - हालांकि टॉसिंग सरल बनाने के बारे में कोसी 2801 का बिंदु भी प्रासंगिक है। (मुझे लगता है यह वास्तव में नहीं होगा क्षेत्रों की प्रकृति के कारण, कई टकराव बनाने, लेकिन ...)

मैं एल्गोरिथ्म "सही पाने के लिए सरल और आसान" मैं पहले से है used in this answer के लिए जाना होगा (इसे लांस देखने के लिए धन्यवाद :) - और जो कि प्रभावी जावा में सूचीबद्ध है, जैसा आपने कहा था। इस मामले में यह समाप्त हो जाएगा:

public int GetHashCode() 
{ 
    int hash = 17; 
    // Suitable nullity checks etc, of course :) 
    hash = hash * 23 + StreetAddress.GetHashCode(); 
    hash = hash * 23 + RuralRoute.GetHashCode(); 
    hash = hash * 23 + City.GetHashCode(); 
    hash = hash * 23 + Province.GetHashCode(); 
    hash = hash * 23 + Country.GetHashCode(); 
    hash = hash * 23 + PostalCode.GetHashCode(); 
    return hash; 
} 

यह बिल्कुल शून्य नहीं है।

public static int GetNullSafeHashCode<T>(this T value) where T : class 
{ 
    return value == null ? 1 : value.GetHashCode(); 
} 

तो आप उपयोग कर सकते: आप सी # 3 उपयोग कर रहे हैं अगर आप एक एक्सटेंशन विधि पर विचार करना चाहते हो सकता है

public int GetHashCode() 
{ 
    int hash = 17; 
    // Suitable nullity checks etc, of course :) 
    hash = hash * 23 + StreetAddress.GetNullSafeHashCode(); 
    hash = hash * 23 + RuralRoute.GetNullSafeHashCode(); 
    hash = hash * 23 + City.GetNullSafeHashCode(); 
    hash = hash * 23 + Province.GetNullSafeHashCode(); 
    hash = hash * 23 + Country.GetNullSafeHashCode(); 
    hash = hash * 23 + PostalCode.GetNullSafeHashCode(); 
    return hash; 
} 

आप इस और भी आसान बनाने के लिए एक पैरामीटर सरणी विधि उपयोगिता बना सकते हैं :

public static int GetHashCode(params object[] values) 
{ 
    int hash = 17; 
    foreach (object value in values) 
    { 
     hash = hash * 23 + value.GetNullSafeHashCode(); 
    } 
    return hash; 
} 

और से कॉल करने की:

public int GetHashCode() 
{ 
    return HashHelpers.GetHashCode(StreetAddress, RuralRoute, City, 
            Province, Country, PostalCode); 
} 

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

+1

एक और समाधान इक्वालिटी कॉम्पैयर का उपयोग करना है। Default.GetHashCode (someValue)। यह एक शून्य सुरक्षित हैशिंग तंत्र है और 2.0 – JaredPar

+0

के बाद से ढांचे में है धन्यवाद, यह सही काम करता है। आपके GetNullSafeHashCode() विधि में एक छोटी सी त्रुटि है: इसमें "यह" गुम है। – cdmckay

+0

दोह! बहुत बहुत धन्यवाद। फिक्स्ड। –

5

ऐसा न करें क्योंकि ऑब्जेक्ट अलग-अलग हो सकता है हैशकोड समान है।

Think की

"StreetAddress" + "RuralRoute" + "City" 

बनाम
"Street" + "AddressRural" + "RouteCity" 

दोनों क्षेत्रों में एक ही hashCode लेकिन अलग अलग सामग्री होगा।

+0

यह एक अच्छी बात है, मैं था है माना जाता है कि। हालांकि यह अभ्यास में होने की संभावना नहीं लगती है। – cdmckay

+1

क्या आसानी से खेतों के बीच एक डिलीमीटर लगाकर हल किया जा सकता है? (जैसे '" स्ट्रीट एड्रेस "+"/डेलीमीटर/"+" रूटर रूट "+"/डेलीमीटर/"+" सिटी "' कुछ भाषाओं में एकाधिक असाइनमेंट से बचने के लिए एक चर हो सकता है?) – simonra

0

बात की इस तरह के लिए, आप लागू करने के लिए चाहते हो सकता है IEqualityComparer<Address>:

public class Address : IEqualityComparer<Address> 
{   
    // 
    // member declarations 
    // 

    bool IEqualityComparer<Address>.Equals(Address x, Address y) 
    { 
     // implementation here 
    } 

    int IEqualityComparer<Address>.GetHashCode(Item obj) 
    { 
     // implementation here 
    } 
} 

आप ऑर्डर करने के लिए IComparable<Address> को भी कार्यान्वित कर सकता है ...

-4
public string getfourDigitEncryptedText(string input) { 
    int hashCode = input.hashCode(); 
    string hstring = (new StringBuilder()).append(hashCode).append("").toString(); 
    string rev_hstring = (new StringBuilder(hstring)).reverse().toString(); 
    string parts[] = rev_hstring.trim().split(""); 
    int prefixint = 0; 
    for(int i = 1; i <= parts.length - 3; i++) 
     prefixint += integer.parseInt(parts[i]); 
    string prefixstr = "0"; 
    if((new integer(prefixint)).toString().length() < 2) 
     prefixstr = (new StringBuilder()).append((new integer(prefixint)).toString()).append("5").toString(); 
    else if((new integer(prefixint)).toString().length() > 2) 
     prefixstr = "79"; 
    else 
     prefixstr = (new integer(prefixint)).toString(); 
    string finalstr = (new StringBuilder()).append(prefixint).append(rev_hstring.substring(3, 5)).toString(); 
    return finalstr; 
} 
+0

क्या आप अपना कोड क्या कर सकते हैं इसका स्पष्टीकरण प्रदान कर सकते हैं? – DeanOC

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

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