2010-02-17 15 views
52

मैंने डेवलपर्स को नीचे दिए गए कोडों का उपयोग वैकल्पिक रूप से देखा है। इनके बीच सटीक अंतर क्या है, और कौन से मानक मानक से जाते हैं? वे एक ही कर रहे हैं के रूप में Action और Func<T> रूप में अच्छी तरह एक प्रतिनिधि है:एक्शन <T> बनाम प्रतिनिधि घटना

public event Action<EmployeeEventAgs> OnLeave; 
public void Leave() 
{ 
    OnLeave(new EmployeeEventAgs(this.ID)); 
} 

वी.एस.

public delegate void GoOnLeave(EmployeeEventAgs e); 
public event GoOnLeave OnLeave; 
public void Leave() 
{ 
    OnLeave(new EmployeeEventAgs(this.ID)); 
} 

उत्तर

48

Fwiw, न तो उदाहरण मानक .NET सम्मेलनों का उपयोग करता है।

public event EventHandler<EmployeeEventArgs> Leave; 

"चालू" उपसर्ग एक संरक्षित विधि है कि घटना को जन्म देती है के लिए आरक्षित किया जाना चाहिए:: नहीं

protected virtual void OnLeave(EmployeeEventArgs e) { 
    var handler = Leave; 
    if (handler != null) handler(this, e); 
} 

आप इसे ऐसा करने के लिए EventHandler<T> सामान्य घटना घोषित करना चाहिए रास्ता, लेकिन कोई भी तुरंत पैटर्न को पहचान लेगा, अपना कोड समझ जाएगा और इसका उपयोग कैसे करेगा और उसे अनुकूलित करेगा।

और इसका एक अच्छा लाभ है कि कस्टम प्रतिनिधि घोषणा के बीच चयन करने के लिए मजबूर नहीं किया जा रहा है और Action<>, EventHandler<> सबसे अच्छा तरीका है। जो आपके प्रश्न का उत्तर देता है।

+29

यह अच्छी सलाह है, लेकिन मुझे नहीं लगता कि यह –

+2

प्रश्न का उत्तर देता है क्या आपने उद्देश्य के लिए 'छोड़ने वाले हैंडलर को प्रतिनिधि के रूप में घोषित किया था: सार्वजनिक __event__ EventHandler <> ... उद्देश्य पर? जब आप ईवेंट को उजागर करने वाले वर्ग के साथ काम करते हैं तो 'इवेंट' कीवर्ड काफी गेम परिवर्तक होता है, क्योंकि इसके बिना कोई भी' obj.Leave = someHandler' 'obj.Leave + = someHandler के बजाय पूरे ईवेंट संग्रह को मिटा सकता है। ' –

+3

नहीं, यह एक गलती थी। तीन साल में कोई भी नहीं देखा :) धन्यवाद! –

4

हाँ, एक्शन और समारोह साधारणत: सुविधा के प्रतिनिधियों कि 3.5 clr में परिभाषित किया गया है।

एक्शन, फनक और लैम्ब्डा सभी सिंटैक्टिकल चीनी और प्रतिनिधियों का उपयोग करने के लिए सुविधा हैं।

उनके बारे में कुछ भी जादू नहीं है। इस कार्यक्षमता को 2.0 कोड में जोड़ने के लिए कई लोगों ने सरल 2.0 एडन लाइब्रेरी लिखी हैं।

20

Action<T> बिल्कुल के रूप में delegate void ... (T t)

Func<T> ही है ठीक उसी delegate T ...()

+0

नहीं * बिल्कुल वही * ... उनके पास एक ही हस्ताक्षर है, लेकिन वे असाइनमेंट संगत नहीं हैं (जो आईएमएचओ बहुत दुर्भाग्यपूर्ण है ...) –

+4

क्या इससे उन्हें बिल्कुल वही नहीं मिलता है?क्या एक्स और वाई अलग हैं: सार्वजनिक प्रतिनिधि शून्य एक्स (टी टी); सार्वजनिक प्रतिनिधि शून्य वाई (टी टी) शून्य; आप एक दूसरे को असाइन नहीं कर सकते हैं। – pdr

3

You may want to look here के रूप में, यह देखना कि संकलक वास्तव में कार्रवाई के लिए उत्पन्न करता है सबसे अच्छा वर्णन है। आपके द्वारा लिखे गए कार्यों में कोई कार्यात्मक अंतर नहीं है, केवल छोटा, अधिक सुविधाजनक वाक्यविन्यास।

6

कार्रवाई पूरी प्रतिनिधि घोषणा के लिए सिर्फ एक शॉर्टकट है।

public delegate void Action<T>(T obj) 

http://msdn.microsoft.com/en-us/library/018hxwa8.aspx

कौन सा अपने संगठनों कोडिंग मानकों/शैली पर निर्भर करेगा उपयोग करने के लिए एक।

3

सामान्यतः, वे बराबर हैं। लेकिन एक घटना के प्रकार के लिए एक प्रतिनिधि का उपयोग कर के संदर्भ में, सम्मेलन (जहां टी EventArgs विरासत) eventhandler उपयोग करने के लिए है:

public event EventHandler<EmployeeEventArgs> Left; 

public void Leave() 
{ 
    OnLeft(this.ID); 
} 

protected virtual void OnLeft(int id) 
{ 
    if (Left != null) { 
     Left(new EmployeeEventArgs(id)); 
    } 
} 
0

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

20

कोड की निम्न दो पंक्तियों लगभग बराबर हैं:

public event EventHandler<EmployeeEventAgs> Leave; 

अंतर ईवेंट हैंडलर विधि के हस्ताक्षर में है:

public event Action<EmployeeEventAgs> Leave; 

के रूप में करने का विरोध किया। आप कार्रवाई के साथ पहला तरीका अपनाते हैं, आप हो सकता है:

public void LeaveHandler(EmployeeEventAgs e) { ... } 

और फिर इस:

obj.Leave += LeaveHandler; 
दूसरे दृष्टिकोण के साथ

, LeaveHandler जरूरतों के हस्ताक्षर अलग होने की:

public void LeaveHandler(object sender, EmployeeEventAgs e) { ... } 

यह बहुत महत्वपूर्ण नोटिस वें है दोनों मामलों में event कीवर्ड मौजूद है। event कीवर्ड के माध्यम से स्पष्ट रूप से घोषित एक कार्यक्रम अब कक्षा का क्षेत्र नहीं है। इसके बजाय यह ईवेंट संपत्ति बन जाता है। घटना गुण नियमित गुणों के समान होते हैं, सिवाय इसके कि उनके पास get या set एक्सेसर्स नहीं हैं। कंपाइलर उन्हें += और -= असाइनमेंट के बाएं तरफ उपयोग करने की अनुमति देता है (एक ईवेंट हैंडलर जोड़ना या निकालना)। पहले से असाइन किए गए ईवेंट हैंडलर, या को उस कक्षा के बाहर ईवेंट को आमंत्रित करने का कोई तरीका नहीं है जो घोषित करता है।

तो घटना कीवर्ड दोनों उदाहरणों में याद आ रही थी, तो आप कोई त्रुटि या चेतावनी के साथ निम्न कार्रवाई कर सकता है:

obj.Leave = LeaveHandler; 

जो किसी भी पंजीकृत संचालकों मिटा सकते हैं और उन्हें LeaveHandler withe की जगह लेगा।

इसके अलावा, आप भी इस कॉल कर सकते हैं: यदि आप एक ईवेंट बनाने का इरादा

obj.Leave(new EmployeeEventAgs()); 

दो उपरोक्त उदाहरण, एक विरोधी पैटर्न माना जाता है। एक ईवेंट को केवल स्वामी ऑब्जेक्ट द्वारा बुलाया जाना चाहिए और अवांछनीय ग्राहकों को हटाने की अनुमति नहीं देनी चाहिए। event कीवर्ड .NET का प्रोग्रामेटिक निर्माण है जो आपको ईवेंट के सही उपयोग से चिपकने में मदद करता है।

उपरोक्त दिमाग में, मेरा मानना ​​है कि कई लोग EventHandler दृष्टिकोण तक चिपके रहते हैं क्योंकि event कीवर्ड के बिना EventHandler का उपयोग करने की संभावना अधिक नहीं है। कार्रवाइयों के उपयोग के व्यापक दायरे हैं, वे घटनाओं के रूप में उपयोग किए जाने पर स्वाभाविक रूप से नहीं दिखते हैं। उत्तरार्द्ध, निश्चित रूप से, एक व्यक्तिगत राय है, क्योंकि घटना कोडर दृष्टिकोण संभवतः मेरे कोडिंग प्रथाओं में बहुत कठिन हो गया है। फिर भी, अगर कार्रवाई ठीक से उपयोग की जाती है, तो घटनाओं के लिए उनका उपयोग करने का अपराध नहीं है।

+1

+1। – Joel

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