2009-08-26 20 views
48

निम्नलिखित कोड को देखते हुए, क्या कोई तरीका है कि मैं विधि ए के संस्करण ए के संस्करण को कॉल कर सकता हूं?मैं एक ओवरराइड वर्चुअल विधि के 'आधार कार्यान्वयन' को कैसे कॉल कर सकता हूं?

class A 
{ 
    virtual void X() { Console.WriteLine("x"); } 
} 

class B : A 
{ 
    override void X() { Console.WriteLine("y"); } 
} 

class Program 
{ 
    static void Main() 
    { 
    A b = new B(); 
    // Call A.X somehow, not B.X... 
    } 

उत्तर

78

सी # भाषा निर्माणों का उपयोग करना, आप स्पष्ट रूप से से आधार समारोह बाहर A या B के दायरे फोन नहीं कर सकते हैं। यदि आपको वास्तव में ऐसा करने की ज़रूरत है, तो आपके डिज़ाइन में कोई दोष है - यानी यह फ़ंक्शन प्रारंभ करने के लिए वर्चुअल नहीं होना चाहिए, या बेस फ़ंक्शन का हिस्सा अलग-अलग गैर वर्चुअल फ़ंक्शन में निकाला जाना चाहिए।

आप अंदर B.X से हालांकि A.X

class B : A 
{ 
    override void X() { 
    base.X(); 
    Console.WriteLine("y"); 
    } 
} 

कॉल कर सकते हैं लेकिन यह कुछ और ही है।

जैसा कि साशा Truf this answer में इंगित करता है, आप इसे आईएल के माध्यम से कर सकते हैं। आप शायद इसे प्रतिबिंब के माध्यम से भी पूरा कर सकते हैं, क्योंकि टिप्पणियां टिप्पणियों में बताती हैं।

+6

(हाय बस रिकार्ड के लिए, किसी को 'मूर्ख-ट्रिक का टैग हटा दिया है कि मैं जोड़ा, और फिर किसी को: ऐसा करने के लिए, व्युत्पन्न वर्ग में विधि घोषित किया जाना चाहिए new के रूप में अन्यथा यह इंगित करने वाली टिप्पणी को हटा दिया गया है, ऐसा लगता है कि मैं वास्तव में चाहता हूं/ऐसा करने की ज़रूरत है। ऐसे लोगों के बारे में अधिसूचित होने के लिए उपयोगी होगा जो लोग SO पर करना चाहते हैं। – mackenir

+0

अंदर बी से कॉलिंग एएक्स() एकमात्र ऐसी स्थिति है जिसे मैं देख सकता हूं कि आपको बार-बार इसे कॉल करने की आवश्यकता है। मान लें कि आपके पास बेस क्लास सदस्यों के साथ प्रतिलिपि विधि थी, फिर नए सदस्यों के लिए कॉपी कार्यक्षमता जोड़ने और बेस.copy() को कॉल करने के लिए इसे ओवरराइड करें ताकि सभी कॉपी हो जाएं। – steviesama

+0

दिलचस्प, मैंने सोचा होगा कि इसे प्रतिबिंब के माध्यम से पूरा किया जा सकता है? – mhand

6

आप नहीं कर सकते हैं, और आपको नहीं करना चाहिए। पॉलीमोर्फिज्म यही है, ताकि प्रत्येक ऑब्जेक्ट में कुछ "आधार" चीजें करने का अपना तरीका हो।

7

आप इसे कर सकते हैं, लेकिन उस बिंदु पर नहीं जो आपने निर्दिष्ट किया है। B के संदर्भ में, आप base.X() पर कॉल करके A.X() पर आ सकते हैं।

4

मैं अब इसका इतिहास प्रश्न जानता हूं। लेकिन अन्य googlers के लिए: आप इस तरह कुछ लिख सकते हैं। लेकिन इसके लिए बेस क्लास में बदलाव की आवश्यकता है जो बाहरी पुस्तकालयों के साथ बेकार बनाता है।

class A 
{ 
    void protoX() { Console.WriteLine("x"); } 
    virtual void X() { protoX(); } 
} 

class B : A 
{ 
    override void X() { Console.WriteLine("y"); } 
} 

class Program 
{ 
    static void Main() 
    { 
    A b = new B(); 
    // Call A.X somehow, not B.X... 
    b.protoX(); 


    } 
10

आप इसे सी # द्वारा नहीं कर सकते हैं, लेकिन आप MSIL को संपादित कर सकते हैं।

आईएल अपने मुख्य विधि का कोड:

.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    .maxstack 1 
    .locals init (
     [0] class MsilEditing.A a) 
    L_0000: nop 
    L_0001: newobj instance void MsilEditing.B::.ctor() 
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: callvirt instance void MsilEditing.A::X() 
    L_000d: nop 
    L_000e: ret 
} 

आप opcode अगर विधि में घोषित किया जाता है कॉल

L_0008: call instance void MsilEditing.A::X() 
2

यह असंभव है करने के लिए callvirt से L_0008 में बदलना चाहिए व्युत्पन्न वर्ग overrides के रूप में। ।

public class Base { 

    public virtual string X() { 
     return "Base"; 
    } 
} 
public class Derived1 : Base 
{ 
    public new string X() 
    { 
     return "Derived 1"; 
    } 
} 

public class Derived2 : Base 
{ 
    public override string X() { 
     return "Derived 2"; 
    } 
} 

Derived1 a = new Derived1(); 
Base b = new Derived1(); 
Base c = new Derived2(); 
a.X(); // returns Derived 1 
b.X(); // returns Base 
c.X(); // returns Derived 2 

See fiddle here

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

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