2009-06-17 15 views
28
class A 
{ 
    public override int GetHashCode() 
    { 
     return 1; 
    } 
} 
class B : A 
{ 
    public override int GetHashCode() 
    { 
     return ((object)this).GetHashCode(); 
    } 
} 

new B().GetHashCode() 

जैसे दूसरे स्तर की बेस क्लास विधि को कॉल करने के लिए यह स्टैक ओवरफ़्लो करता है। मैं B.GetHashCode() से Object.GetHashCode() पर कैसे कॉल कर सकता हूं?बेस -बेस.गेटहाशकोड()

संपादित करें: B अब A से विरासत में मिला है।

+3

क्या आपका मतलब कक्षा बी से कक्षा बी का उत्तराधिकारी होना था? – AakashM

+0

@AakashM - अच्छी जगह! मैंने मानसिक रूप से इसे ध्यान में रखकर डाला, यह वहां नहीं है; मुझे लगता है कि हम मान सकते हैं कि यह होना चाहिए ... –

+0

यह चाहिए। मैंने इसे जोड़ा है। – usr

उत्तर

17

(संपादित करें - पढ़ने में भूलना प्रश्न)

आप मूल object.GetHashCode() संस्करण प्राप्त करना चाहते हैं; आप नहीं कर सकते - कम से कम, जब तक A यह कुछ ऐसा द्वारा उपलब्ध कराता है नहीं:

protected int GetBaseHashCode() { return base.GetHashCode();} 

(और B कॉल GetBaseHashCode() है)।

कारण यह बहता है कि GetHashCode (स्पष्ट रूप से) वर्चुअल है - इससे कोई फर्क नहीं पड़ता कि आप इसे object पर डालें; यह अभी भी वास्तविक वस्तु में सबसे अधिक व्युत्पन्न कार्यान्वयन से शुरू होता है, यानी B.GetHashCode() (इसलिए विस्फोट)।

+0

ऐसा लगता है कि मैंने इसे भी गलत तरीके से पढ़ा था। अच्छी पकड़। – Welbog

+0

असल में, मैंने सोचा कि आप एक विधि के एक विशिष्ट संस्करण को कॉल करने के लिए प्रतिबिंब का उपयोग कर सकते हैं, भले ही यह वर्चुअल हो। – LBushkin

+3

@LBushkin - मैंने यह भी सोचा; लेकिन जब मैंने इसे थोड़ी देर पहले कोशिश की (कस्टम आईएल और "कॉलवर्ट" के बजाय "कॉल" का उपयोग करके) सीएलआई ने इसे खारिज कर दिया और कहा कि यह रनटाइम को अस्थिर कर सकता है (और यह एक मामूली उदाहरण के लिए था)। –

13

आप RuntimeHelpers.GetHashCode(object) उपयोग कर सकते हैं वस्तु की मूल हैश कोड प्राप्त करने के:

class A 
    { 
    public override int GetHashCode() 
    { 
     Console.WriteLine("base hashcode is: " + base.GetHashCode()); 

     return 1; 
    } 
    } 

    class Program 
    { 
    public static void Main(string[] args) 
    { 
     A a = new A(); 

     Console.WriteLine("A's hashcode: " + a.GetHashCode()); 

     Console.WriteLine("A's original hashcode: " + RuntimeHelpers.GetHashCode(a)); 
    } 
    } 

यह निम्न परिणाम पैदा करता है:

आधार hashCode है: 54,267,293
एक के hashCode: 1
ए का मूल हैशकोड: 54267293

यदि आप प्रतिबिंबक में RuntimeHelpers.GetHashCode(object) पर एक नज़र डालें, तो आप देखेंगे कि यह आंतरिक स्थैतिक विधि object.InternalGetHashCode(object) पर कॉल करता है। यदि आप और जानना चाहते हैं, तो GetHashCode के डिफ़ॉल्ट कार्यान्वयन के संबंध में this question पर एक नज़र डालें।

7

मैं बाहरी पुस्तकालय का उपयोग कर रहा हूं और मैं बेस.बेस को भी कॉल करना चाहता था (कुछ मामलों में एक बग की वजह से)। कुछ शोध करने के बाद मैं इस पृष्ठ http://www.rsdn.ru/forum/dotnet/475911.aspx

में आए यह काफी सरल है: आप अपने विधि कॉल और वस्तु सूचक को * इस (या वस्तु आप चाहते हैं)

स्थापित करने के लिए आधार वर्ग आप चाहते हैं का उपयोग कर एक प्रतिनिधि को परिभाषित तो, महत्वपूर्ण कोड है:

public delegate void MD(); 

public void Test() { 
     // A is the base class you want to call the method. 
     A a = new A(); 
     // Create your delegate using the method name "M" with the instance 'a' of the base class 
     MD am = (MD)Delegate.CreateDelegate(typeof(MD), a, "M"); 
     // Get the target of the delegate and set it to your object (this in most case) 
     am.GetType().BaseType.BaseType.GetField("_target", BindingFlags.Instance BindingFlags.NonPublic).SetValue(am, this); 
     // call the method using the delegate. 
     am(); 
    } 
+0

"काफी सरल" मैंने सोचा नहीं जब मैंने कोड पढ़ा लेकिन यह एक आकर्षण की तरह काम करता है :-)! –

0

आप तो आप एक स्थिर विधि के साथ उप-उप विधि की कार्यक्षमता को लागू कर सकते सब-सब वर्ग के कोड को संशोधित कर सकते हैं। इस स्थैतिक (सार्वजनिक) विधि के पहले पैरामीटर वर्ग के एक वस्तु के रूप में है। इस तरह आप इसे हर जगह से कॉल कर सकते हैं।

class A 
{ 
    public static int CalcHashCode(A obj) 
    { 
     return 1; 
    } 

    public override int GetHashCode() 
    { 
     return CalcHashCode(this); 
    } 
} 
class B : A 
{ 
    public override int GetHashCode() 
    { 
     return A.CalcHashCode(this); 
    } 
}