दिलचस्प पोस्ट
स्थिर पुस्तकालय में उद्देश्य-सी श्रेणियां फ़ंक्शन टेम्पलेट्स के लिए डिफ़ॉल्ट टेम्पलेट तर्क सरणी के लिए नया ऑब्जेक्ट जोड़ें विकल्प टैग के साथ छवियां जोड़ना एक चिड़ियाघर से वर्ष और वर्ष निकालें :: वर्ष वस्तु विशेषता मूल्य पर आधारित DOM में एक तत्व ढूंढें जीसीसी के साथ सी ++ प्रोग्राम संकलित करना क्यों फ़ायरफ़ॉक्स के लिए ग़रक़ीडर की जरूरत है? IPhone ऐप में कस्टम फोंट का प्रयोग करें सीतनिद्रा में होना: इकाई वर्गों पर आधारित डीबी तालिकाओं को स्वचालित रूप से बनाने / अद्यतन करना Cassandra में विभाजन कुंजी, समग्र कुंजी और क्लस्टरिंग कुंजी के बीच का अंतर? जब इनपुट सत्यापन विफल रहता है तो अंगुलोज़ फॉर्म फ़ॉर्म को रोकता है विंडो के किनारे के संबंध में पॉपओवर की एक्स स्थिति के आधार पर बूटस्ट्रैप पॉपओवर की स्थिति बदलने? जावास्क्रिप्ट प्रोटोटाइप ऑब्जेक्ट का उपयोग करते समय इवेंट विधियों में "यह" कीवर्ड मूल्यों का एक एकल, यादृच्छिक संयोजन का चयन करने के लिए एल्गोरिथ्म?

शेडिंग क्या है?

सी # में शब्दावली का अर्थ क्या है? मैंने यह लिंक पढ़ा है, लेकिन इसे पूरी तरह समझ नहीं आया।

वेब के समाधान से एकत्रित समाधान "शेडिंग क्या है?"

छायांकन एक आधार वर्ग में एक विधि छुपाता है। आपके द्वारा लिंक किए गए प्रश्न में उदाहरण का उपयोग करना:

class A { public int Foo(){ return 5;} public virtual int Bar(){return 5;} } class B : A { public new int Foo() { return 1;} public override int Bar() {return 1;} } 

कक्षा B वर्चुअल पद्धति Bar ओवरराइड करता है यह गैर-आभासी विधि Foo छुपाता है (छाया) ओवरराइड ओवरराइड कीवर्ड का उपयोग करता है नए कीवर्ड के साथ छायांकन किया जाता है

उपरोक्त कोड में, यदि आपने कक्षा B में Foo विधि को परिभाषित करते हुए नए कीवर्ड का उपयोग नहीं किया है, तो आप इस संकलक की चेतावनी प्राप्त करेंगे:

 'test.B.Foo()' hides inherited member 'test.A.Foo()'. Use the new keyword if hiding was intended. 
  • ओवरराइडिंग: आधार क्लास पर मौजूदा विधि को फिर से परिभाषित करना
  • छायांकन: आधार हस्ताक्षर के रूप में एक ही हस्ताक्षर के साथ एक पूरी तरह से नई पद्धति का निर्माण करना

मान लीजिए मेरे पास एक बेस क्लास है जो एक आभासी विधि लागू करता है:

 public class A { public virtual void M() { Console.WriteLine("In AM()."); } } 

मेरे पास व्युत्पन्न वर्ग भी है जो विधि को परिभाषित करता है M:

 public class B : A { // could be either "new" or "override", "new" is default public void M() { Console.WriteLine("In BM()."); } } 

अब, मान लीजिए कि मैं इस तरह एक प्रोग्राम लिखूंगा:

 A alpha = new B(); // it's really a B but I cast it to an A alpha.M(); 

मेरे पास दो अलग-अलग विकल्प हैं, जिन्हें मैं लागू करना चाहता हूं। डिफ़ॉल्ट व्यवहार एम के ए संस्करण को कॉल करना है। (यदि आप BM() लिए " new " कीवर्ड लागू करते हैं (यह व्यवहार के समान है।)

इसे "छायांकन" कहा जाता है, जब हमारे पास एक ही नाम के साथ एक विधि होती है लेकिन एक अलग व्यवहार जब बेस क्लास से फोन किया जाता है।

वैकल्पिक रूप से, हम BM() पर " override " निर्दिष्ट कर सकते थे इस मामले में, alpha.M() ने बी के संस्करण को एम। कहा होगा।

छायांकन में बाल वर्ग में एक नई परिभाषा के साथ बेस क्लास पद्धति को छुपाने पर मिलती है।

छिपाने और ओवरराइड करने के बीच के तरीकों से तरीकों को लागू किया जाता है।

इस प्रकार, जब कोई आभासी विधि ओवरराइड हो जाती है, आधार क्लास के विधि कॉल तालिका के लिए कॉल एड्रेस को बाल नियमन के पते से बदल दिया जाता है

दूसरी ओर, जब एक विधि छिपी जाती है, तो बच्चा कक्षा के विधि कॉल टेबल में एक नया पता जोड़ा जाता है।

जब प्रश्न में एक विधि को कॉल किया जाता है:

  1. विधि कॉल तालिका वर्ग प्रकार प्राप्त किया जाता है, यदि हम बेस क्लास के संदर्भ के साथ प्रयोग कर रहे हैं तो बेस क्लास विधि तालिका प्राप्त की जाती है, अगर हमारे पास बाल वर्ग का कोई संदर्भ है, तो बाल वर्ग पद्धति तालिका प्राप्त की जाती है।
  2. तालिका में विधि खोजी जाती है, अगर यह पाया जाता है तो आविष्कार होता है, अन्यथा बेस क्लास विधि तालिका खोज की जाती है।

यदि हम बाल वर्ग के संदर्भ के साथ विधि का आह्वान करते हैं तो व्यवहार समान होता है, यदि विधि ओवरराइड की जाती है, तो विधि पता बेस क्लास में पाई जाएगी, अगर विधि छिपाई गई थी, विधि पता पाया जाएगा बाल वर्ग, और क्योंकि यह पहले से ही पाया गया है, आधार वर्ग की तालिका खोज नहीं की जाएगी।

यदि हम आधार वर्ग के संदर्भ के साथ विधि का आह्वान करते हैं तो व्यवहार में परिवर्तन होता है अध्यारोपित होने पर, विधि पता आधार वर्ग प्रविष्टि को अधिलेखित करता है, हम मूल पद्धति को कॉल करेंगे, भले ही आधार वर्ग के लिए कोई संदर्भ रखते हुए। छायांकन के साथ, बेस क्लास विधि तालिका (जो केवल एक ही दृश्यमान है, जैसा कि हम बेस क्लास के लिए संदर्भ रखते हैं) में वर्चुअल पद्धति का पता होता है, और इसलिए, बेस क्लास विधि को बुलाया जाएगा।

सामान्य रूप से छिपाने में एक बुरा विचार है, क्योंकि यह हमारे संदर्भ के आधार पर एक उदाहरण के व्यवहार पर एक अंतर का परिचय देता है।

केंट के सही उत्तर पर विस्तार

जब किसी विधि को बुलाया जाएगा, तो मुझे यह पसंद करना चाहिए जब मैं निम्नलिखित के साथ ओवरराइड करने के बारे में सोचना चाहता हूं

  • शेडिंग: कॉल की गई विधि कॉल किए जाने वाले बिंदु पर संदर्भ के प्रकार पर निर्भर करती है
  • ओवरराइडिंग: कॉल की गई विधि कॉल किए जाने वाले बिंदु पर ऑब्जेक्ट के प्रकार पर निर्भर करती है।

यहाँ शेडिंग पर एक एमएसडीएन लेख है भाषा उदाहरण विज़ुअल बेसिक में हैं (दुर्भाग्य से एमएसडीएन पर कोई समकक्ष सी # पृष्ठ नहीं है), लेकिन यह आमतौर पर अवधारणाओं के साथ सौदा करता है और उम्मीद है कि आपको वैसे भी समझने में मदद करनी चाहिए।

संपादित करें: ऐसा लगता है कि छायांकन पर सी # आलेख है, सिवाय इसके कि इसे सी # में छिपा हुआ है। इसके अलावा, यह पृष्ठ एक अच्छा अवलोकन प्रदान करता है

यदि आप बेस क्लास विधि को छिपाना चाहते हैं, बेस में आधार पर आभासी विधि का उपयोग करें।

यदि आप चाइल्ड क्लास विधि को छिपाना चाहते हैं, आधार में नया उपयोग करें [बेस में गैर-आभासी विधि] -> छाया

 Base B=new Child() 

B.VirtualMethod() -> बाल कक्षा विधि कॉल

B.NonVirtualMethod() -> बेस क्लास विधि कॉल करता है

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

  private static int x = 10; static void Main(string[] args) { int x = 20; if (Program.x == 10) { Console.WriteLine(Program.x); } Console.WriteLine(x);} 

आउटपुट:

10 20