2009-03-23 8 views
33

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

+1

कैसे फिर से सवाल का जवाब है कि आप इसे समझने में मदद करने जा रहे हैं? –

+12

क्या हर कोई चीजों को ठीक उसी तरह बताता है? क्या स्कूल में कुछ शिक्षक नहीं थे जिन्हें आपने सोचा था कि दूसरों को बेहतर कहां है? –

+1

यह ध्यान दिया जाना चाहिए कि छायांकन एक वीबी शब्द है - सी # इस छिपाने की कॉल करता है। –

उत्तर

29
  • अधिभावी: एक आधार वर्ग पर किसी मौजूदा विधि को पुनर्परिभाषित
  • पीछा: एक आधार वर्ग
+0

नई विधि - एक ही हस्ताक्षर के साथ या? – User

+1

+1 अच्छी तरह संक्षेप में! – Csharp

+2

ध्यान दें कि छाया के साथ आप रिटर्न प्रकार बदल सकते हैं। –

3

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

संपादित करें: लगता है जैसे शैडोइंग पर एक C# article है वहाँ , सिवाय इसके कि यह सी # में छुपा कहा जाता है। इसके अलावा, this page एक अच्छा अवलोकन प्रदान करता है।

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

मैं भी एक व्युत्पन्न वर्ग है कि यह भी एक विधि एम परिभाषित करता है:

+0

ऐसा इसलिए है क्योंकि इसे सी # में छिपाया जाता है: http://msdn.microsoft.com/en-us/library/aa691133(VS.71).aspx –

+0

आह, जो समझाएगा। – Noldorin

20

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

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

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

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

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

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

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

44

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

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. 
+0

इसका कार्यात्मक उद्देश्य क्या है? आप इसे ओवरराइड करने के बजाय कुछ क्यों छिपाएंगे? – sab669

+3

@ sab669: कल्पना कीजिए कि आप एक गैर वर्चुअल विधि को "ओवरराइड" करना चाहते हैं। आप वास्तव में इसे ओवरराइड नहीं कर सकते हैं, इसलिए इसके बजाय आप इसे छाया करते हैं। यह एक आदर्श समाधान नहीं है क्योंकि यह सभी मामलों में एक ओवरराइड वर्चुअल विधि की तरह कार्य नहीं करता है, लेकिन जब व्युत्पन्न कक्षा से बुलाया जाता है, तो यह अपेक्षित काम करेगा। यह अपेक्षाकृत दुर्लभ है कि आप यह करना चाहते हैं, लेकिन जब आपको इसकी आवश्यकता होती है तो आपको वास्तव में इसकी आवश्यकता होती है। –

+0

आह, तो यह सिर्फ एक प्रकार के रूप में मौजूद है "ठीक है कि विधि वर्चुअल नहीं है, और एक कारण या किसी अन्य कारण से मैं इसे आभासी नहीं बना सकता, इसलिए नए को" तरह की चीज़ "करना होगा? – sab669

-3

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

+0

यह एक टिप्पणी की तरह लगता है। – Neolisk

10

शेडिंग में बाल वर्ग में एक नई परिभाषा के साथ बेस क्लास विधि को छिपाने पर शामिल है।

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

इस तरह, जब वर्चुअल विधि ओवरराइड हो जाती है, तो बेस क्लास की विधि कॉल तालिका के लिए कॉल पता को बाल दिनचर्या के पते से बदल दिया जाता है।

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

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

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

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

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

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

8

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

जब disambiguating जब जो विधि बुलाया जाएगा, मैं निम्नलिखित

  • पीछा साथ अधिभावी बनाम पीछा के बारे में सोचना चाहते: विधि कहा जाता है के प्रकार पर निर्भर बिंदु पर संदर्भ
  • ओवरराइडिंग: कॉल किया गया तरीका उस बिंदु पर ऑब्जेक्ट के प्रकार पर निर्भर करता है जिस पर कॉल किया जाता है।
-4
private static int x = 10; 


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

आउटपुट:

+1

यह सवाल का जवाब नहीं देता है – alu

2

आप आधार वर्ग विधि को छिपाने के लिए, आधार [आधार में आभासी विधि]

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

Base B=new Child() 

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

B.NonVirtualMethod() -> कॉल आधार वर्ग विधि

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