2010-09-02 11 views
80

Func<> क्या है और इसके लिए क्या उपयोग किया जाता है?Func क्या है, यह कैसे और कब उपयोग किया जाता है

+2

यह एक विशिष्ट हस्ताक्षर वाले प्रतिनिधियों के लिए सिर्फ एक शॉर्टकट है। नीचे दिए गए उत्तरों को पूरी तरह से समझने के लिए आपको प्रतिनिधियों को समझने की आवश्यकता होगी ;-) –

+1

@ ओडेड के जवाब में यह कहता है, 'यदि आपके पास कोई ऐसा फ़ंक्शन है जो पैरामीटर के आधार पर विभिन्न प्रकारों को वापस करने की आवश्यकता है, तो आप एक Func प्रतिनिधि का उपयोग कर सकते हैं, रिटर्न टाइप निर्दिष्ट करना। – Lijo

उत्तर

57

Func<T> एक विधि के लिए एक पूर्वनिर्धारित प्रतिनिधि प्रकार है जो T प्रकार के कुछ मान देता है।

दूसरे शब्दों में, आप इस विधि का उपयोग उस विधि को संदर्भित करने के लिए कर सकते हैं जो T का कुछ मान देता है। जैसे

public static string GetMessage() { return "Hello world"; } 

सामान्य प्रतिनिधियों कि पिछले सामान्य पैरामीटर के प्रकार वापसी इस

Func<string> f = GetMessage; 
+0

लेकिन यह एक स्थिर एक-तर्क फ़ंक्शन का प्रतिनिधित्व भी कर सकता है =) –

+2

@ आर्क-कुन नो, यह सही नहीं है। 'Func ' की परिभाषा 'प्रतिनिधि ट्रेशल्ट Func ()' है। कोई तर्क नहीं 'Func 'एक ऐसा फ़ंक्शन होगा जो एक तर्क लेता है। –

+3

नहीं, मैं सही हूँ। 'स्थिर int OneArgFunc (यह स्ट्रिंग i) {वापसी 42; } '' Func f = "foo" .neArgFunc; '। =) –

9

Func<T1,R> और अन्य पूर्वनिर्धारित सामान्य Func प्रतिनिधियों (Func<T1,T2,R>, Func<T1,T2,T3,R> और अन्य) की तरह संदर्भित किया जा सकता है।

यदि आपके पास कोई ऐसा फ़ंक्शन है जो पैरामीटर के आधार पर विभिन्न प्रकारों को वापस करने की आवश्यकता है, तो आप रिटर्न प्रकार निर्दिष्ट करते हुए Func प्रतिनिधि का उपयोग कर सकते हैं।

66

इसे प्लेसहोल्डर के रूप में सोचें। यह काफी उपयोगी हो सकता है जब आपके पास एक निश्चित पैटर्न का पालन करने वाला कोड हो लेकिन किसी विशेष कार्यक्षमता से बंधे रहने की आवश्यकता न हो।

उदाहरण के लिए, Enumerable.Select एक्सटेंशन विधि पर विचार करें।

  • पैटर्न है: एक क्रम में हर आइटम के लिए, उस आइटम (जैसे, एक संपत्ति) से कुछ मूल्य का चयन करें और एक नया इन मूल्यों से मिलकर अनुक्रम पैदा करते हैं।
  • प्लेसहोल्डर है: कुछ चयनकर्ता फ़ंक्शन जो वास्तव में ऊपर वर्णित अनुक्रम के लिए मान प्राप्त करता है।

यह विधि किसी भी ठोस समारोह के बजाय Func<T, TResult> लेती है। इससे इसे में संदर्भ में उपयोग किया जा सकता है जहां उपर्युक्त पैटर्न लागू होता है।

तो उदाहरण के लिए, मेरे पास List<Person> है और मैं सिर्फ सूची में प्रत्येक व्यक्ति का नाम चाहता हूं। मैं यह कर सकता:

var names = people.Select(p => p.Name); 

या कहते हैं कि मैं हर व्यक्ति की उम्र हैं:

var ages = people.Select(p => p.Age); 

यह करते ही आप देख सकते हैं कि कैसे मैं लाभ उठाने के लिए एक का प्रतिनिधित्व ही कोड में सक्षम था पैटर्न (Select के साथ) दो विभिन्न फ़ंक्शंस (p => p.Name और p => p.Age) के साथ।

विकल्प हर बार Select का एक अलग संस्करण लिखना होगा जब आप एक अलग प्रकार के मूल्य के लिए अनुक्रम स्कैन करना चाहते थे।तो जैसा कि ऊपर एक ही प्रभाव प्राप्त करने के लिए, मैं की आवश्यकता होगी:

// Presumably, the code inside these two methods would look almost identical; 
// the only difference would be the part that actually selects a value 
// based on a Person. 
var names = GetPersonNames(people); 
var ages = GetPersonAges(people); 

एक प्रतिनिधि प्लेसहोल्डर के रूप में अभिनय के साथ, मैं अपने आप को इस तरह के मामलों में अधिक से अधिक एक ही पैटर्न को लिखने के लिए होने से मुक्त।

47

Func<T1, T2, ..., Tn, Tr> एक फ़ंक्शन का प्रतिनिधित्व करता है, जो लेता है (टी 1, टी 2, ..., टीएन) तर्क और रिटर्न देता है।

उदाहरण के लिए, यदि आप एक समारोह है, तो:

Func<double, double> f1 = sqr; 
Func<double, double> f2 = x => x * x; 

और फिर का उपयोग बिल्कुल के रूप में आप sqr का प्रयोग करेंगे:

double sqr(double x) { return x * x; } 

आप एक समारोह-चर के कुछ प्रकार के रूप में यह बचत हो सकती है:

f1(2); 
Console.WriteLine(f2(f1(4))); 

आदि

हालांकि याद रखें, यह एक प्रतिनिधि है, अधिक उन्नत जानकारी के लिए दस्तावेज़ीकरण का संदर्भ लें।

+0

एक्सेलेंट उत्तर, लेकिन कीवर्ड स्थिर को भरने के लिए – boctulus

5

यह सिर्फ एक पूर्वनिर्धारित जेनेरिक प्रतिनिधि है। इसका उपयोग करके आपको प्रत्येक प्रतिनिधि को घोषित करने की आवश्यकता नहीं है। एक और पूर्वनिर्धारित प्रतिनिधि है, Action<T, T2...>, जो वही है लेकिन शून्य लौटाता है।

3

मुझे फंक बहुत उपयोगी लगता है जब मैं एक घटक बनाता हूं जिसे "फ्लाई पर" वैयक्तिकृत करने की आवश्यकता होती है।

यह बहुत आसान उदाहरण लें: प्रिंटलिस्ट TConsole घटक।

एक बहुत ही सरल वस्तु जो ऑब्जेक्ट्स की इस सूची को कंसोल पर प्रिंट करती है। आप डेवलपर को आउटपुट को वैयक्तिकृत करने के लिए इसका उपयोग करना चाहते हैं।

उदाहरण के लिए, आप उसे एक कणों के प्रकार के प्रारूप को परिभाषित करने देना चाहते हैं और इसी तरह।

समारोह बिना

सबसे पहले, आप एक वर्ग है कि इनपुट लेने के लिए और कंसोल के लिए मुद्रित करने के लिए स्ट्रिंग उत्पादन के लिए एक इंटरफेस बनाने के लिए किया है।

interface PrindListConsoleRender<T> { 
    String Render(T input); 
} 

तो फिर तुम वर्ग PrintListToConsole कि पिछले बनाई इंटरफेस लेने के लिए और सूची के प्रत्येक तत्व से अधिक इसका इस्तेमाल बनाना होगा।

class PrintListToConsole<T> { 

    private PrindListConsoleRender<T> _renderer; 

    public void SetRenderer(PrindListConsoleRender<T> r) { 
     // this is the poin where I can personalize the render mechanism 
     _renderer = r; 
    } 

    public void PrintToConsole(List<T> list) { 
     foreach (var item in list) { 
      Console.Write(_renderer.Render(item)); 
     } 
    } 
} 

डेवलपर अपने घटक का उपयोग करने की जरूरत है कि करने के लिए है:

1) इंटरफेस

2) PrintListToConsole

class myrenderer : PrindListConsoleRender<int> { 
    public String Render(int input) { 
     return "Number: " + input; 
    } 
} 

class Program { 
    static void Main(string[] args) { 
     var list = new List<int> { 1, 2, 3 }; 
     var printer = new PrintListToConsole<int>(); 
     printer.SetRenderer(new myrenderer()); 
     printer.PrintToConsole(list); 
     string result = Console.ReadLine(); 
    } 
} 

समारोह का उपयोग करने के लिए वास्तविक वर्ग पारित लागू यह बहुत आसान है

घटक आप प्रकार समारोह की एक पैरामीटर को परिभाषित अंदर कि एक समारोह उस प्रकार टी के एक इनपुट पैरामीटर लेने के लिए और एक स्ट्रिंग (कंसोल के लिए उत्पादन)

class PrintListToConsole<T> { 

    private Func<T, String> _renderFunc; 

    public void SetRenderFunc(Func<T, String> r) { 
     // this is the point where I can set the render mechanism 
     _renderFunc = r; 
    } 

    public void StampaFunc(List<T> list) { 
     foreach (var item in list) { 
      Console.Write(_renderFunc(item)); 
     } 
    } 
} 

लौटने के इंटरफेस का प्रतिनिधित्व करते हैं जब डेवलपर उपयोग आपका घटक यह केवल फनक प्रकार के कार्यान्वयन के घटक को पास करता है, यह एक ऐसा फ़ंक्शन है जो कंसोल के लिए आउटपुट बनाता है।

class Program { 
    static void Main(string[] args) { 
     var list = new Array[1, 2, 3]; 
     var printer = new PrintListToConsole<int>(); 
     printer.SetRenderFunc((o) => "Number:" + o); 
     string result = Console.ReadLine(); 
    } 
} 

समारोह आप मक्खी पर एक सामान्य विधि इंटरफेस को परिभाषित करते हैं। आप परिभाषित करते हैं कि इनपुट किस प्रकार का है और आउटपुट किस प्रकार का है। सरल और संक्षिप्त।

+1

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

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

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