2011-09-22 17 views
12

मैं थोड़ा उलझन में हूं कि एक्सटेंशन विधियां कैसे काम करती हैं।सी # एक्सटेंशन विधि प्राथमिकता

यदि मैं इसे सही ढंग से http://msdn.microsoft.com/en-us/library/bb383977.aspx और यह If an extension method has the same signature as a method in the sealed class, what is the call precedence? पढ़ रहा हूं।

फिर निम्नलिखित को "इंस्टेंस" लिखना चाहिए, लेकिन इसके बजाय यह "विस्तार विधि" लिखता है।

interface IFoo 
{ 
} 

class Foo : IFoo 
{ 
    public void Say() 
    { 
     Console.WriteLine("Instance"); 
    } 
} 

static class FooExts 
{ 
    public static void Say(this IFoo foo) 
    { 
     Console.WriteLine("Extension method"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     IFoo foo = new Foo(); 
     foo.Say(); 
    } 
} 

व्यवहार को स्पष्ट करने में किसी भी मदद की सराहना करें।

+0

क्या आप एक विस्तार विधि संकलन के साथ अंतर्निहित विधि को ओवरराइड करना चाहते हैं? – kenny

+0

दूसरी नज़र में या इसे संकलित करने पर, इंटरफ़ेस में Say() नहीं है, इसलिए आपने एक्सटेंशन विधि को क्या कहा है। इंटरफ़ेस में सेव() के साथ संकलक 'सी: \ प्रोजेक्ट \ _play \ एक्सटेंशन मैथ्यूज \ Program.cs (2,1) के साथ शिकायत करता है: त्रुटि CS0116: नामस्थान में फ़ील्ड या विधियों जैसे सदस्यों को सीधे शामिल नहीं किया जा सकता है' – kenny

उत्तर

14

यहाँ बड़ा अंतर यह है कि आप IFoo इंटरफेस के लिए एक विस्तार विधि को परिभाषित किया है, और अपने foo वैरिएबल प्रकार IFoo की है।

अपने कोड इस तरह देखने के लिए था, तो:

Foo foo = new Foo(); 
foo.Say() 

Foo.Say() विधि, निष्पादित किया जाएगा नहीं विस्तार विधि।

मेरी इच्छा है कि मैं आपको इस बारे में पूरी तरह से स्पष्टीकरण दे सकता हूं कि यह क्यों है लेकिन मैं केवल मूल तंत्र को कवर कर सकता हूं। चूंकि आपका चर IFoo प्रकार और Foo का नहीं था, जब संकलक ने यह निर्धारित करने की कोशिश की कि कौन सी विधियां उपलब्ध हैं, तो Foo वर्ग (जैसा भी होना चाहिए) के किसी भी गैर-इंटरफेस विधियों को देखा। हालांकि, एक्सटेंशन विधि Say() उपलब्ध थी, इसलिए उसने इसे आमंत्रित किया।

+2

इसमें जोड़ने के लिए , जब आप 'IFoo foo = ..' का उपयोग करते हैं, तो foo का प्रकार' IFoo' है, भले ही यह 'Foo' के उदाहरण को इंगित करता हो। 'फू फू ...' ऑब्जेक्ट पर विधि को कॉल करता है, 'IFoo foo' 'FooExts.Say (foo) 'तक विस्तार करने के लिए' Say()' का कारण बनता है। आईएल देखने के लिए 'ildasm' चलाएं और .exe को ड्रॉप करें। –

+0

धन्यवाद जिम अच्छी टिप। – Dax70

4

आपके Main में, foo को IFoo के रूप में घोषित किया गया है। जब संकलक Say विधि की तलाश करता है, तो यह केवल एक्सटेंशन विधि पाता है। ऐसा इसलिए है क्योंकि उदाहरण विधि Foo में घोषित की गई है, IFoo में नहीं। कंपाइलर यह नहीं जानता कि परिवर्तनीय fooFoo का उदाहरण होता है; यह सिर्फ वैरिएबल घोषित प्रकार के प्रकार को देखता है।

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