2010-02-09 17 views
13

मुझे कुछ अजीब पता चला कि मैं बेहतर समझने की उम्मीद कर रहा हूं।सी # विधि समूह अजीबता

var all = new List<int[]>{ 
       new int[]{1,2,3}, 
       new int[]{4,5,6}, 
       new int[]{7,8,9} 
       }; 

all.ForEach(n => n.ForEach(i => Console.WriteLine(i))); 

जो के रूप में लिखा जा सकता है:

... 
all.ForEach(n => n.ForEach(Console.WriteLine)); 

कैसे अभी भी वर्तमान आइटम Console.WriteLine को पारित किया है यह लैम्ब्डा अभिव्यक्ति पैरामीटर (i =>) बाहर छोड़ने के लिए संभव है और?

किसी भी अंतर्दृष्टि के लिए धन्यवाद। -किथ

उत्तर

33

Action<T> की तलाश में है। जब आप

n.ForEach(Console.WriteLine); 

बारे में क्या आप यहाँ विधि समूह Console.WriteLine एक Action<T> की भूमिका निभा के सदस्यों में से एक है। कंपाइलर Console.WriteLine का सबसे अच्छा अधिभार देखने के लिए देखेगा जो int के उदाहरण खाता है। वास्तव में, यह ओवरलोड Console.WriteLine(int) का उपयोग करेगा। इसके बाद Action<int> की भूमिका निभाने के लिए इस अधिभार का उपयोग किया जाएगा।

यह कैसे किया जाता है, इस बारे में विवरण के लिए, विनिर्देश के §6.6 (विधि समूह रूपांतरण) देखें।

हालांकि, जब तुम

n.ForEach(i => Console.WriteLine(i)); 

बारे में हम वास्तव में एक बहुत ही अलग Action<int> पहले मामले में है, Action<int>Console.WriteLine(int) था। इधर, Action<int> बराबर है आप

public static void DoSomething(int i) { 
    Console.WriteLine(i); 
} 

और लिखित होने के लिए तो

n.ForEach(DoSomething); 

(बेशक, संकलक जैसा कि ऊपर वर्णित यह पता लगाने की क्या मतलब है एक ही विधि समूह प्रक्रिया के माध्यम से जाना पड़ता है DoSomething द्वारा)।

बिंदु यह है कि पहले मामले में Action<int>Console.WriteLine(int) है। हालांकि, दूसरे मामले में Action<int> एक मध्यम व्यक्ति (लैम्ब्डा अभिव्यक्ति) है जो स्वयं Console.WriteLine(int) पर कॉल करेगा।

+1

++ संकलक की इमेजरी के लिए "खाने" कंसोल का एक अधिभार। राइटलाइन! –

+1

बहुत अच्छी तरह से व्यक्त किया गया। धन्यवाद! – Keith

+0

अच्छा स्पष्टीकरण। –

2

यदि आप वास्तव में क्या हो रहा है, तो यह कम भ्रमित है।

आप एक प्रतिनिधि तर्क के लिए एक विधि पारित कर रहे हैं। अधिकांश समय, हम घटनाओं के संदर्भ में प्रतिनिधियों के बारे में सोचते हैं, लेकिन वे तरीकों के लिए पैरामीटर भी हो सकते हैं। तर्क के बिना किसी ईवेंट में कोई विधि जोड़ा जाने पर यह अजीब प्रतीत नहीं होता है, इस संदर्भ में निष्पादित होने पर यह असामान्य लग रहा है।

लैम्बडास से पहले, आपको यह हर समय करना था, और यह इतना दर्द था कि कोई भी लाइब्रेक की तरह दिखाई देने वाली लाइब्रेरी का उपयोग करने पर विचार नहीं करेगा। Lambdas के साथ, यह करना आसान है, लेकिन आप हमेशा पुराने तरीके से भी कर सकते हैं।

+0

सी # 2।0 में अज्ञात प्रतिनिधि वाक्यविन्यास ('प्रतिनिधि() {}') था, लेकिन यह अभी भी पर्याप्त वाक्य रचनात्मक चीनी नहीं था और LINQ को बहुत गन्दा बना देगा। – Gabe

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