.NET फ्रेमवर्क में लैम्ब्डा और डेलिगेट्स के बीच अंतर क्या है?


86

मुझे यह प्रश्न बहुत अच्छा लगा और मुझे लगा कि मैं अंतर बताने के लिए कुछ इनपुट पर विचार करूंगा।


2
"प्रतिनिधियों" से क्या आपका मतलब प्रतिनिधि प्रकार, या अनाम प्रतिनिधियों से है? वे भी अलग हैं।
16:17 पर क्रिस अम्मारमैन


1
लोग उसके प्रश्न को इतना जटिल क्यों बनाते हैं? बस जवाब दें कि एक प्रतिनिधि क्या है और एक लंबोदर क्या है। जितना संभव हो उतना स्पष्टीकरण दें और उसे चुनें जो उसके लिए उपयुक्त है।
इमर होक्सा

जवाबों:


96

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

कुछ सूक्ष्म अंतरों को छोड़कर लम्बदा अन्य विधियों की तरह हैं।

  1. एक सामान्य विधि को "कथन" में परिभाषित किया गया है और एक स्थायी नाम से बंधा हुआ है, जबकि एक लैम्बडा को "अभिव्यक्ति" में "मक्खी पर" परिभाषित किया गया है और जिसका कोई स्थायी नाम नहीं है।
  2. कुछ लैम्ब्डा का उपयोग .NET एक्सप्रेशन ट्री के साथ किया जा सकता है, जबकि विधियाँ नहीं कर सकती हैं।

एक प्रतिनिधि इस तरह से परिभाषित किया गया है:

delegate Int32 BinaryIntOp(Int32 x, Int32 y);

एक प्रकार का बाइनरीइंटऑनप का एक चर या तो एक विधि या एक लैम्ब्डा उसे सौंपा जा सकता है, जब तक कि हस्ताक्षर एक ही है: दो Int32 तर्क और एक Int32 वापसी।

एक लंबोदर को इस तरह परिभाषित किया जा सकता है:

BinaryIntOp sumOfSquares = (a, b) => a*a + b*b;

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

यहां बताया गया है कि कैसे फनक और एक्शन "सिर्फ लंबोदर के लिए नहीं" हैं:

Int32 DiffOfSquares(Int32 x, Int32 y)
{
  return x*x - y*y;
}

Func<Int32, Int32, Int32> funcPtr = DiffOfSquares;

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

अतिरिक्त मील जा रहे हैं .... C # में फंक्शन लचीले हैं, जिसमें लैम्बडा और डेलिगेट्स का उपयोग किया गया है। लेकिन C # में "प्रथम श्रेणी के कार्य" नहीं हैं। आप उस फ़ंक्शन का प्रतिनिधित्व करने के लिए आवश्यक रूप से एक ऑब्जेक्ट बनाने के लिए एक प्रतिनिधि चर को सौंपे गए फ़ंक्शन के नाम का उपयोग कर सकते हैं। लेकिन यह वास्तव में एक कंपाइलर ट्रिक है। यदि आप एक फंक्शन का नाम डॉट (इसके बाद फंक्शन पर मेंबर एक्सेस करने की कोशिश करते हैं) लिखकर स्टेटमेंट शुरू करते हैं, तो आप पाएंगे कि वहां कोई भी सदस्य रेफरेंस के लिए नहीं है। ऑब्जेक्ट से भी नहीं। यह प्रोग्रामर को उपयोगी (और संभावित रूप से खतरनाक) चीजों को करने से रोकता है जैसे कि विस्तार विधियों को जोड़ना जो किसी भी फ़ंक्शन पर कहा जा सकता है। आप जो सबसे अच्छा कर सकते हैं, वह डेलिगेट वर्ग का ही विस्तार करता है, जो निश्चित रूप से उपयोगी भी है, लेकिन उतना नहीं।

अद्यतन: इसके अलावा Karg के उत्तर को गुमनाम प्रतिनिधियों बनाम विधियों और लैम्ब्डा के बीच के अंतर को स्पष्ट करते हुए देखें ।

अद्यतन 2: जेम्स हार्ट एक महत्वपूर्ण, हालांकि बहुत ही तकनीकी बनाता है, ध्यान दें कि लैम्ब्डा और डेलिगेट्स .NET इकाइयां नहीं हैं (यानी सीएलआर में एक प्रतिनिधि या लैम्ब्डा की कोई अवधारणा नहीं है), बल्कि वे फ्रेमवर्क और भाषा निर्माण हैं।


अच्छे खर्च। हालांकि मुझे लगता है कि आपका मतलब "प्रथम श्रेणी के कार्य" हैं, न कि "प्रथम श्रेणी की वस्तुएँ"। :)
ibz

1
आप सही हे। मुझे लिखने के दौरान वाक्य अलग था ("C # फ़ंक्शन वास्तव में प्रथम श्रेणी की वस्तुएं नहीं हैं") और इसे बदलना भूल गए। धन्यवाद!
क्रिस अम्मारमैन

एक सामान्य विधि को "कथन" में परिभाषित किया गया है एक कथन एक अनिवार्य कार्यक्रम के अनुक्रम में एक क्रिया है, संभवतः एक अभिव्यक्ति पर आधारित है। क्या एक विधि-परिभाषा एक अलग व्याकरणिक संरचना नहीं है? विधि-परिभाषा docs.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/…
Max

32

सवाल थोड़ा अस्पष्ट है, जो आपको मिल रहे उत्तरों में व्यापक असमानता की व्याख्या करता है।

आपने वास्तव में पूछा था कि .NET फ्रेमवर्क में लैम्ब्डा और डेलिगेट्स के बीच क्या अंतर है; यह कई चीजों में से एक हो सकता है। क्या आप पूछ रहे हो:

  • C # (या VB.NET) भाषा में लैम्ब्डा एक्सप्रेशन और अनाम डेलिगेट्स के बीच अंतर क्या है?

  • System.Linq.Expressions.LambdaExpression ऑब्जेक्ट और .NET 3.5 में System.Delegate ऑब्जेक्ट के बीच अंतर क्या है?

  • या उन चरम सीमाओं के बीच या आसपास कहीं कुछ?

कुछ लोग आपको इस सवाल का जवाब देने की कोशिश कर रहे हैं कि 'सी # लैंबडा एक्सप्रेशन और .NET.Delegate?' के बीच अंतर क्या है, जो पूरी तरह से समझ में नहीं आता है।

.NET फ्रेमवर्क अपने आप में अनाम डेलिगेट्स, लैम्ब्डा एक्सप्रेशन या क्लोज़र की अवधारणाओं को नहीं समझता है - ये सभी भाषा विनिर्देशों द्वारा परिभाषित की गई चीजें हैं। इस बारे में सोचें कि C # कंपाइलर क्लोजर स्टेट को होल्ड करने के लिए मेंबर वेरिएबल्स के साथ एक जेनरेट किए गए क्लास में एक मेथड का अनाउंसमेंट किस तरीके से करता है; .NET के लिए, प्रतिनिधि के बारे में कुछ भी अनाम नहीं है; यह लिखने वाले C # प्रोग्रामर के लिए बस गुमनाम है। यह एक प्रतिनिधि प्रकार को सौंपे गए लंबोदर अभिव्यक्ति के समान रूप से सच है।

.NET क्या समझता है एक प्रतिनिधि का विचार है - एक प्रकार जो एक विधि हस्ताक्षर का वर्णन करता है, जिसके उदाहरण विशिष्ट वस्तुओं पर विशिष्ट विधियों के लिए या तो बाध्य कॉल का प्रतिनिधित्व करते हैं, या किसी विशेष प्रकार पर किसी विशेष विधि के लिए अनबाउंड कॉल करते हैं, जिसके खिलाफ आह्वान किया जा सकता है उस प्रकार की कोई भी वस्तु, जहां उक्त विधि उक्त हस्ताक्षर का पालन करती है। इस प्रकार के सभी System.Delegate से विरासत में मिलते हैं।

.NET 3.5 भी System.Linq.Expressions नामस्थान का परिचय देता है, जिसमें कोड अभिव्यक्तियों का वर्णन करने के लिए कक्षाएं होती हैं - और जो विशेष प्रकार या ऑब्जेक्ट पर विधियों के लिए बाध्य या अनबाउंड कॉल का प्रतिनिधित्व भी कर सकती हैं। लैंबडाएक्सप्रेशन उदाहरणों को वास्तविक प्रतिनिधियों में संकलित किया जा सकता है (जिसमें अभिव्यक्ति की संरचना के आधार पर एक गतिशील विधि कोडेन्ग की जाती है, और एक प्रतिनिधि सूचक इसे लौटा दिया जाता है)।

C # में आप उक्त प्रकार के एक लैंबडा एक्सप्रेशन को निर्दिष्ट करके System.Expressions.Expression प्रकारों के उदाहरण उत्पन्न कर सकते हैं, जो रनटाइम पर अभिव्यक्ति के निर्माण के लिए उपयुक्त कोड का उत्पादन करेगा।

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

और लंबोदर भाव अभिव्यक्ति पीढ़ी का समर्थन करते हैं।


3
बढ़िया जानकारी! आपने मुझे परावर्तक और आईएल को देखने के लिए प्रेरित किया। मुझे नहीं पता था कि लैम्ब्डा उत्पन्न कक्षाओं में होता है, लेकिन यह अब सही समझ में आता है कि मैं इसके बारे में सोचता हूं।
क्रिस अम्मारमैन

20

एक अंतर यह है कि एक गुमनाम प्रतिनिधि मापदंडों को छोड़ सकता है जबकि एक लंबोदर को सटीक हस्ताक्षर से मेल खाना चाहिए। दिया हुआ:

public delegate string TestDelegate(int i);

public void Test(TestDelegate d)
{}

आप इसे निम्नलिखित चार तरीकों से कह सकते हैं (ध्यान दें कि दूसरी पंक्ति में एक अनाम प्रतिनिधि है जिसमें कोई पैरामीटर नहीं है):

Test(delegate(int i) { return String.Empty; });
Test(delegate { return String.Empty; });
Test(i => String.Empty);
Test(D);

private string D(int i)
{
    return String.Empty;
}

आप एक लैम्ब्डा अभिव्यक्ति में पास नहीं हो सकते हैं जिसमें कोई पैरामीटर नहीं है या एक ऐसी विधि है जिसमें कोई पैरामीटर नहीं है। इन्हें अनुमति नहीं है:

Test(() => String.Empty); //Not allowed, lambda must match signature
Test(D2); //Not allowed, method must match signature

private string D2()
{
    return String.Empty;
}

13

प्रतिनिधि फ़ंक्शन पॉइंटर्स / मेथड पॉइंटर्स / कॉलबैक (अपनी पिक लें) के बराबर हैं, और लैम्ब्डा बहुत अधिक सरलीकृत अनाम फ़ंक्शन हैं। कम से कम यही तो मैं लोगों को बताता हूं।


बिल्कुल सही! इसमें कोई फर्क नही है"। वे दो अलग-अलग चीजें हैं।
ibz

3

मेरे पास इसके साथ एक टन का अनुभव नहीं है, लेकिन जिस तरह से मैं इसका वर्णन करता हूं वह यह है कि एक प्रतिनिधि किसी भी फ़ंक्शन के आसपास एक आवरण है, जबकि एक लंबोदर अभिव्यक्ति स्वयं एक अनाम फ़ंक्शन है।


3

एक प्रतिनिधि हमेशा मूल रूप से एक फ़ंक्शन पॉइंटर होता है। एक लैम्ब्डा एक प्रतिनिधि में बदल सकता है, लेकिन यह एक LINQ अभिव्यक्ति पेड़ में भी बदल सकता है। उदाहरण के लिए,

Func<int, int> f = x => x + 1;
Expression<Func<int, int>> exprTree = x => x + 1;

पहली पंक्ति एक प्रतिनिधि का उत्पादन करती है, जबकि दूसरी एक अभिव्यक्ति वृक्ष का निर्माण करती है।


2
यह सच है, लेकिन उनके बीच का अंतर यह है कि वे दो पूरी तरह से अलग अवधारणाएं हैं । यह सेब और संतरे की तुलना करने जैसा है। दान शील्ड का जवाब देखें।
ibz

2

लैम्ब्डा बस एक प्रतिनिधि पर सिंटैक्टिक चीनी होते हैं। कंपाइलर लैम्बदास को डेलीगेट्स में परिवर्तित करता है।

ये वही हैं, मुझे विश्वास है:

Delegate delegate = x => "hi!";
Delegate delegate = delegate(object x) { return "hi";};

2
इन उदाहरणों में से कोई भी संकलन नहीं है। यहां तक ​​कि अगर आप Delegate'प्रतिनिधि' से उदाहरण का नाम बदलते हैं , जो एक कीवर्ड है।
स्टीव कूपर १

2

एक प्रतिनिधि एक समारोह हस्ताक्षर है; कुछ इस तरह

delegate string MyDelegate(int param1);

प्रतिनिधि एक निकाय को लागू नहीं करता है।

लैम्बडा एक फ़ंक्शन कॉल है जो प्रतिनिधि के हस्ताक्षर से मेल खाता है। उपरोक्त प्रतिनिधि के लिए, आप किसी भी का उपयोग कर सकते हैं;

(int i) => i.ToString();
(int i) => "ignored i";
(int i) => "Step " + i.ToString() + " of 10";

Delegateप्रकार बुरी तरह से है, हालांकि नाम पर है; एक प्रकार की वस्तु बनाने से Delegateवास्तव में एक चर बनता है जो कार्यों को पकड़ सकता है - वे लंबोदर, स्थिर तरीके या वर्ग विधियां हो सकते हैं।


जब आप MyDelegate प्रकार का एक वैरिएबल बनाते हैं, तो यह वास्तव में रनटाइम प्रकार नहीं होता है। रनटाइम प्रकार डेलिगेट है। इसमें कंपाइलर ट्रिक शामिल हैं कि कैसे डेलिगेट्स, लैम्ब्डा और एक्सप्रेशन ट्री संकलित करते हैं, जो मुझे लगता है कि कोड का मतलब है कि चीजें सच नहीं हैं।
क्रिस अम्मरमन

2

एक प्रतिनिधि एक विशेष पैरामीटर सूची और वापसी प्रकार के साथ एक विधि का संदर्भ है। इसमें ऑब्जेक्ट शामिल हो सकता है या नहीं।

एक लंबोदर-अभिव्यक्ति अनाम फ़ंक्शन का एक रूप है।


2

एक प्रतिनिधि, फ़ंक्शन पॉइंटर्स की एक कतार है, एक प्रतिनिधि को आमंत्रित करने से कई तरीके हो सकते हैं। एक लंबोदर अनिवार्य रूप से एक अनाम विधि घोषणा है जिसे संकलक द्वारा अलग-अलग तरीके से व्याख्या की जा सकती है, यह इस संदर्भ पर निर्भर करता है कि इसे किस रूप में उपयोग किया जाता है।

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

अंतर वास्तव में यह है कि एक लंबोदर एक तरीका है जो किसी अन्य अभिव्यक्ति के अंदर एक विधि को परिभाषित करता है, जबकि एक प्रतिनिधि एक वास्तविक वस्तु प्रकार है।


2

यह स्पष्ट है कि सवाल यह था कि "मेमने और अनाम प्रतिनिधियों के बीच अंतर क्या है ?" यहां सभी उत्तरों में से केवल एक व्यक्ति ने इसे सही पाया - मुख्य अंतर यह है कि लैम्ब्डा का उपयोग अभिव्यक्ति के पेड़ और साथ ही प्रतिनिधियों को बनाने के लिए किया जा सकता है।

आप MSDN पर अधिक पढ़ सकते हैं: http://msdn.microsoft.com/en-us/library/bb397687.aspx


1

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

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

इसलिए जब कुछ लोग कह सकते हैं कि लैम्ब्डा प्रतिनिधियों के लिए सिंथेटिक चीनी है, तो मैं कहूंगा कि प्रतिनिधियों को सी # में लैम्ब्डा में लोगों को ढील देने के लिए एक पुल है।


1

कुछ बुनियादी यहाँ। "डेलिगेट" वास्तव में एक चर के लिए नाम है जो एक विधि या लैम्ब्डा का संदर्भ रखता है

यह एक अनाम विधि है -

(string testString) => { Console.WriteLine(testString); };

जैसा कि अनाम विधि में कोई नाम नहीं है, हमें एक प्रतिनिधि की आवश्यकता है जिसमें हम इन विधि या अभिव्यक्ति दोनों को असाइन कर सकते हैं। एक्स के लिए।

delegate void PrintTestString(string testString); // declare a delegate

PrintTestString print = (string testString) => { Console.WriteLine(testString); }; 
print();

लंबोदर अभिव्यक्ति के साथ भी। आमतौर पर हमें उन्हें इस्तेमाल करने के लिए प्रतिनिधि की आवश्यकता होती है

s => s.Age > someValue && s.Age < someValue    // will return true/false

हम इस अभिव्यक्ति का उपयोग करने के लिए एक फंक प्रतिनिधि का उपयोग कर सकते हैं।

Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;

bool result = checkStudentAge ( Student Object);

0

लैम्ब्डा प्रतिनिधियों के सरलीकृत संस्करण हैं। उनके पास बंद प्रतिनिधियों के कुछ गुण हैं जैसे अनाम प्रतिनिधि, लेकिन यह भी आपको निहित टाइपिंग का उपयोग करने की अनुमति देता है। इस तरह एक लंबोदर:

something.Sort((x, y) => return x.CompareTo(y));

एक प्रतिनिधि के साथ आप क्या कर सकते हैं की तुलना में बहुत अधिक संक्षिप्त है:

something.Sort(sortMethod);
...

private int sortMethod(SomeType one, SomeType two)
{
    one.CompareTo(two)
}

आपका मतलब है कि लंबोदर सरलीकृत अनाम तरीके (प्रतिनिधि नहीं) हैं। विधियों (अनाम या नहीं) की तरह, उन्हें एक प्रतिनिधि चर को सौंपा जा सकता है।
लुकास

0

एक उदाहरण मैं अपने लंगड़ा ब्लॉग पर थोड़ी देर के लिए रखा। कहते हैं कि आप कार्यकर्ता थ्रेड से एक लेबल अपडेट करना चाहते थे। मुझे डेलमेटस, एनोन डेलिगेट्स और 2 प्रकार के लैम्ब्डा का उपयोग करके उस लेबल को 1 से 50 तक अपडेट करने के 4 उदाहरण मिले हैं।

 private void button2_Click(object sender, EventArgs e) 
     { 
         BackgroundWorker worker = new BackgroundWorker(); 
         worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
         worker.RunWorkerAsync(); 
     } 

     private delegate void UpdateProgDelegate(int count); 
     private void UpdateText(int count) 
     { 
         if (this.lblTest.InvokeRequired) 
         { 
             UpdateProgDelegate updateCallBack = new UpdateProgDelegate(UpdateText); 
             this.Invoke(updateCallBack, new object[] { count }); 
         } 
         else 
         { 
             lblTest.Text = count.ToString(); 
         } 
     } 

     void worker_DoWork(object sender, DoWorkEventArgs e) 
     {   
         /* Old Skool delegate usage.  See above for delegate and method definitions */ 
         for (int i = 0; i < 50; i++) 
         { 
             UpdateText(i); 
             Thread.Sleep(50); 
         } 

         // Anonymous Method 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke((MethodInvoker)(delegate() 
             { 
                 lblTest.Text = i.ToString(); 
             })); 
             Thread.Sleep(50); 
         } 

         /* Lambda using the new Func delegate. This lets us take in an int and 
          * return a string.  The last parameter is the return type. so 
          * So Func<int, string, double> would take in an int and a string 
          * and return a double.  count is our int parameter.*/ 
         Func<int, string> UpdateProgress = (count) => lblTest.Text = count.ToString(); 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke(UpdateProgress, i); 
             Thread.Sleep(50); 
         } 

         /* Finally we have a totally inline Lambda using the Action delegate 
          * Action is more or less the same as Func but it returns void. We could 
          * use it with parameters if we wanted to like this: 
          * Action<string> UpdateProgress = (count) => lblT…*/ 
         for (int i = 0; i < 50; i++) 
         { 
             lblTest.Invoke((Action)(() => lblTest.Text = i.ToString())); 
             Thread.Sleep(50); 
         } 
     }

0

मुझे लगता है कि आपके प्रश्न की चिंता c # है और .NET नहीं है, क्योंकि आपके प्रश्न की अस्पष्टता के कारण, .NET अकेले नहीं मिलता है - अर्थात, सी # के बिना - प्रतिनिधियों और लंबोदर अभिव्यक्तियों की समझ।

A ( सामान्य , तथाकथित सामान्य प्रतिनिधियों के विरोध में , cf बाद में) प्रतिनिधि को typedefफ़ंक्शन सूचक प्रकार के c ++ के एक प्रकार के रूप में देखा जाना चाहिए , उदाहरण के लिए c ++ में:

R (*thefunctionpointer) ( T ) ;

typeedef का प्रकार thefunctionpointerजो किसी प्रकार के ऑब्जेक्ट को लेने और किसी ऑब्जेक्ट के प्रकार Tको वापस करने वाले फ़ंक्शन का संकेत है R। आप इसे इस तरह उपयोग करेंगे:

thefunctionpointer = &thefunction ;
R r = (*thefunctionpointer) ( t ) ; // where t is of type T

जहां thefunctionएक समारोह होगा Tऔर एक लौट रहा है R

सी # में आप के लिए जाना होगा

delegate R thedelegate( T t ) ; // and yes, here the identifier t is needed

और आप इसे इस तरह उपयोग करेंगे:

thedelegate thedel = thefunction ;
R r = thedel ( t ) ; // where t is of type T

जहां thefunctionएक समारोह में एक Tऔर एक वापस ले जाएगा R। यह प्रतिनिधियों के लिए है, जिसे सामान्य प्रतिनिधि कहा जाता है।

अब, आपके पास c # में जेनेरिक डेलिगेट्स भी हैं, जो ऐसे डेलीगेट्स हैं, जो जेनेरिक हैं, यानी "templated" हैं इसलिए बोलने के लिए, जिससे c ++ एक्सप्रेशन का उपयोग किया जा सके। उन्हें इस तरह परिभाषित किया गया है:

public delegate TResult Func<in T, out TResult>(T arg);

और आप उन्हें इस तरह से उपयोग कर सकते हैं:

Func<double, double> thefunctor = thefunction2; // call it a functor because it is
                                                // really as a functor that you should
                                                // "see" it
double y = thefunctor(2.0);

जहां thefunction2एक कार्य तर्क के रूप में होता है और वापस लौटता है double

अब कल्पना कीजिए कि इसके बजाय thefunction2मैं एक "फ़ंक्शन" का उपयोग करना चाहूंगा, जो कि एक वक्तव्य द्वारा, अब के लिए कहीं भी परिभाषित नहीं है, और यह कि मैं बाद में कभी नहीं लिखूंगा। तब c # हमें इस फ़ंक्शन की अभिव्यक्ति का उपयोग करने की अनुमति देता है । अभिव्यक्ति से मेरा तात्पर्य "गणितीय" (या कार्यात्मक, कार्यक्रमों से चिपकना) है, इसकी अभिव्यक्ति, उदाहरण के लिए: double xमैं एक सहयोगी से जुड़ूंगाdouble x*x । गणित में आप इसे "\ mapsto" लेटेक्स प्रतीक का उपयोग करके लिखते हैं । सी # में कार्यात्मक संकेतन उधार लिया गया है =>:। उदाहरण के लिए :

Func<double, double> thefunctor = ( (double x) => x * x ); // outer brackets are not
                                                           // mandatory

(double x) => x * xएक अभिव्यक्ति है । यह एक प्रकार नहीं है, जबकि प्रतिनिधि (सामान्य या नहीं) हैं।

नैतिकता? अंत में, क्या एक प्रतिनिधि (सम्मान। सामान्य प्रतिनिधि) है, अगर फ़ंक्शन पॉइंटर प्रकार नहीं है (सम्मान। लिपटे + स्मार्ट + जेनेरिक फ़ंक्शन सूचक प्रकार), हुह? कुछ और ! यह और वह देखें ।


-1

खैर, वास्तव में ओवरसाइम्प्लीफाइड संस्करण यह है कि एक लैंबडा एक अनाम फ़ंक्शन के लिए सिर्फ शॉर्टहैंड है। एक प्रतिनिधि केवल अनाम कार्यों की तुलना में बहुत अधिक कर सकता है: घटनाओं, अतुल्यकालिक कॉल और कई विधि श्रृंखला जैसी चीजें।


1
lambdas का उपयोग इवेंट हैंडलर के रूप में किया जा सकता है; बटन.क्लिक + = (प्रेषक, EventArgs) => {MessageBox.Show ("क्लिक"); } और जिसे अतुल्यकालिक रूप से नया सिस्टम कहा जाता है। थ्रेडिंग। () (> = कंसोल। "(" एक थ्रेड पर निष्पादित ")) प्रारंभ ();
कूपर में स्टीव कूपर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.