2010-01-29 13 views
9

मान लीजिए हमने:विधि संकल्प आदेश

public class FooBase 
{ 
    public void Write(byte value) 
    { 
     //something 
    } 

    public void Write(int value) 
    { 
     //something 
    } 
} 

public class Foo : FooBase 
{ 
    public void Write(decimal value) 
    { 
     //something 
    } 
} 
इस से

:

 var writer = new Foo(); 

     writer.Write(5);   //calls Write(decimal) !! 
     writer.Write((byte)6); //calls Write(decimal) !! 

लिखें (दशमलव) अधिभार कॉल करेंगे। क्यूं कर? और मैं लिखें (int) या लिखें (बाइट) कैसे कॉल कर सकता हूं?

+0

कुछ "विधि संकल्प आदेश" के साथ काम करने के लिए प्रश्न का नाम बदलने का सुझाव दें। – dss539

उत्तर

7

आप Write(byte) इस तरह कह सकते हैं:

((FooBase)writer).Write((byte)6); 

आम तौर पर, सी # एक अधिभार प्रकार सीधे पर परिभाषित का उपयोग करें और अपने तर्क डाली बजाय एक अधिभार एक माता पिता के प्रकार पर परिभाषित उपयोग करने के लिए पसंद करेंगे।

इस तरह की शैली में बेस क्लास विधि को छाया देने वाली विधि के लिए यह खराब शैली है।

+0

बिल्कुल। वास्तव में सबसे अच्छा समाधान अस्पष्टता से बचने के लिए बेहतर नामों का उपयोग करना है। – captncraig

+0

मुझे लगता है कि यह गलत है: जब आप बेस क्लास में लेखक उदाहरण डालते हैं, तो यह अभी भी व्युत्पन्न वर्ग का एक ही उदाहरण है, इसलिए इसकी ओवरलोडेड विधि निष्पादित की जाएगी। क्या मैं कुछ भूल रहा हूँ? – Isantipov

+0

यह एक उदाहरण है, जहां तक ​​ऑब्जेक्ट स्वयं स्मृति में मौजूद है। हालांकि कास्टिंग करके, आप उस उदाहरण को किसी अन्य प्रकार के रूप में इलाज करने के लिए संकलक को प्रभावी ढंग से बता रहे हैं। आईडीई अब अधिभार को पहचान नहीं पाएगा। – EnderWiggin

16

हाँ, यह ऐसा करेगा। यह प्रभावी रूप से मेरा brainteaser #1 है। यह वास्तव में इस अर्थ में अनुमान नहीं लगाता है कि इसका सामान्य रूप से उपयोग किया जाता है - यह अधिभार संकल्प है। यही वह जगह है जहां आपको कल्पना में देखना होगा।

अब, Writer का संकलन-समय प्रकार Foo है।

जब आप writer.Write फोन, संकलक प्रकार Foo के साथ शुरू और जब तक यह एक विधि मूल रूप से उस प्रकार है कि यह वैध तरीके से बहस आपके द्वारा दिए गए के साथ कॉल कर सकते हैं में घोषित पाता है अपनी तरह से ऊपर प्रकार hiearchy काम करेंगे। जैसे ही यह एक पाया जाता है, यह पदानुक्रम आगे नहीं जाता है।

अब, 5 परिवर्तनीय है करने के लिए decimal (और इसलिए 5 के बाद यह विशेष रूप से byte को कास्ट किया है) - तो Foo.Write(decimal) अपने विधि कॉल के लिए एक लागू समारोह सदस्य है - और कि क्या कहा जाता हो जाता है। यह FooBase.Write ओवरलोड पर भी विचार नहीं करता है, क्योंकि यह पहले से ही एक मैच मिला है।

अभी तक, यह उचित है - विचार यह है कि मूल प्रकार के लिए एक विधि जोड़ना मौजूदा कोड के लिए ओवरलोड रिज़ॉल्यूशन नहीं बदलना चाहिए जहां बच्चे के प्रकार को इसके बारे में पता नहीं है। ओवरराइडिंग शामिल होने पर यह थोड़ा नीचे गिर जाता है। के अपने कोड थोड़ा परिवर्तन करते हैं - मैं Foo में, byte संस्करण को निकालने Write(int) आभासी बनाने के लिए और ओवरराइड यह करने के लिए जा रहा हूँ:

public class FooBase 
{ 
    public virtual void Write(int value) 
    { 
     //something 
    } 
} 

public class Foo : FooBase 
{ 
    public override void Write(int value) 
    { 
     //something 
    } 

    public void Write(decimal value) 
    { 
     //something 
    } 
} 

अब क्या new Foo().Write(5) क्या करेंगे? यह अभी भी कॉल Foo.Write(decimal) होगा - क्योंकि Foo.Write(int) फू में घोषित नहीं किया गया था, केवल वहाँ अधिरोहित। यदि आप override से new बदलते हैं तो इसे कॉल किया जाएगा, क्योंकि उसके बाद ब्रांड की नई विधि घोषणा के रूप में गिना जाता है।

मुझे लगता है कि पहलू प्रतिद्वंद्वी है - और संस्करण के लिए इसकी आवश्यकता नहीं है, जैसे कि आप बच्चे वर्ग में एक विधि को ओवरराइड कर रहे हैं, आप स्पष्ट रूप से बेस क्लास में जानते हैं।

कहानी का नैतिक: ऐसा करने की कोशिश न करें। आप भ्रमित लोगों को खत्म कर देंगे। यदि आप किसी वर्ग से प्राप्त होते हैं, तो उसी नाम के साथ नई विधियां न जोड़ें, लेकिन यदि आप संभवतः इसकी सहायता कर सकते हैं तो एक अलग हस्ताक्षर।

+0

मैंने आपके मस्तिष्क के बारे में सोचा जब मैंने यह प्रश्न भी पढ़ा ... –

+0

निष्कर्ष के लिए +1। ऐसा मत करो। – jeroenh

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