2012-05-22 13 views
5

प्रतिनिधि: मैं समझता हूं। लेकिन जब मैं घटना में जाता हूं, तो कई चीजें मुझे बहुत समझ में नहीं आती हैं। मैंने पुस्तक, एमएसडीएन और नेटवर्क पर कुछ सरल उदाहरण पढ़े, दोनों में समान संरचनाएं हैं। उदाहरण के लिए, यहां लिंक है: Event Exampleमुझे शुद्ध प्रतिनिधि और घटना फ़ील्ड के बीच अंतर नहीं समझा

मैं पहला उदाहरण लेता हूं, लेखक ने कहा कि यह सी # घटना के बारे में सबसे आसान उदाहरण है। public event TickHandler Tick:

public class Metronome 
{ 
    public event TickHandler Tick; 
    public EventArgs e = null; 
    public delegate void TickHandler(Metronome m, EventArgs e); 
    public void Start() 
    { 
     while (true) 
     { 
      System.Threading.Thread.Sleep(3000); 
      if (Tick != null) 
      { 
       Tick(this, e); 
      } 
     } 
    } 
} 

public class Listener 
{ 
    public void Subscribe(Metronome m) 
    { 
     m.Tick += new Metronome.TickHandler(HeardIt); 
    } 
    private void HeardIt(Metronome m, EventArgs e) 
    { 
     System.Console.WriteLine("HEARD IT"); 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     Metronome m = new Metronome(); 
     Listener l = new Listener(); 
     l.Subscribe(m); 
     m.Start(); 
    } 
} 

आप लाइन नोटिस कर सकते हैं:

यहाँ अपने कोड है। जब मैं public TickHandler Tick में बदलता हूं, तो प्रोग्राम अभी भी वही चलाता है। लेकिन नई लाइन मैं समझता हूं क्योंकि यह सिर्फ एक शुद्ध प्रतिनिधि है।

तो, मेरा प्रश्न है: event का वास्तविक उद्देश्य पंक्ति में कीवर्ड: public event TickHandler Tick है। यह बहुत महत्वपूर्ण है, क्योंकि सभी उदाहरण हमेशा इस तरह उपयोग करते हैं, लेकिन मैं समझा नहीं सकता क्यों।

धन्यवाद :)

उत्तर

8

प्रतिनिधियों और घटनाओं संबंधित अवधारणाओं हैं, लेकिन वे नहीं एक ही बात कर रहे हैं।

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

एक घटना उनमें से न तो है। यह एक प्रकार का सदस्य है - एक जोड़ी जोड़ने/निकालने के तरीकों, घटना से सदस्यता लेने या सदस्यता समाप्त करने के लिए एक प्रतिनिधि लेना। जब आप foo.SomeEvent += handler; या foo.SomeEvent -= handler; का उपयोग करते हैं तो जोड़ें और निकालें विधियों का उपयोग किया जाता है।

यह बहुत ही समान है कि संपत्ति वास्तव में प्राप्त/सेट विधियों की एक जोड़ी है (या संभवतः केवल दो में से एक)।

जब आप इस तरह की एक क्षेत्र की तरह घटना घोषित:

public event TickHandler Tick; 

संकलक अपने वर्ग जो कर रहे हैं कुछ हद तक इस तरह के सदस्यों को जोड़ता है:

private TickHandler tick; 

public event TickHandler 
{ 
    add { tick += value; } 
    remove { tick -= value; } 
} 

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

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

// Not real C#, but I wish it were... 
public event TickHandler Tick { add; remove; } 

मैं एक whole article बल्कि और अधिक विस्तार है, जो आपके लिए उपयोगी हो सकता है में जा रहा है।

7

event कीवर्ड मूल रूप से अपने delegate पर आपरेशन प्रतिबंधित करता है। अब आप इसे = ऑपरेटर का उपयोग करके मैन्युअल रूप से असाइन नहीं कर सकते हैं।

आप केवल जोड़ सकते हैं या (+= का उपयोग कर) को हटाने आपके घटना के प्रतिनिधियों, एक के बाद एक (-= का उपयोग)। यह कुछ ग्राहकों को अन्य सब्सक्रिप्शन को "ओवरराइट" करने से रोकने के लिए किया जाता है।

परिणामस्वरूप, आप ऐसा नहीं कर सकते: m.Tick = new Metronome.TickHandler(HeardIt)

+2

ध्यान दें कि ये प्रतिबंध केवल उस प्रकार के बाहर हैं जहां 'ईवेंट' घोषित किया गया है। अंदर, आप जो भी चाहें कर सकते हैं, ताकि आप 'टिक (यह, ई)' जैसी चीजें कर सकें। आप इसे 'निजी टिकहैंडलर' के रूप में पारदर्शी रूप से सार्वजनिक जोड़/निकालने के तरीकों के साथ सोच सकते हैं जिन्हें + = और - = के माध्यम से एक्सेस किया जाता है। –

+2

मुझे लगता है कि यह कहने के लिए भ्रामक है कि "ऑपरेशन को प्रतिबंधित करता है" - यह मौलिक रूप से एक अलग तरह का सदस्य घोषित करता है (एक घटना)। मुझे लगता है कि यह मानसिक रूप से घटनाओं और प्रतिनिधियों को काफी महत्वपूर्ण रूप से अलग करने में मदद करता है। –

1

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

0

मुझे लगता है कि प्रतिनिधि और घटना का उपयोग करने के बीच मुख्य अंतर यह है कि ईवेंट केवल सर्वर द्वारा उठाया जा सकता है (जिसका अर्थ है लेखक कक्षा)

यदि आप event कीवर्ड को हटाते हैं तो आप m.Tick(sender,e)Listener में अन्यथा नहीं बढ़ा सकते हैं।

public class Listener 
{ 
    public void Subscribe(Metronome m) 
    { 
    m.Tick += new Metronome.TickHandler(HeardIt); 
    } 

    private void RaisTick(object sender, EventArgs e) 
    { 
     m.Tick(sender,e); 
    } 
    private void HeardIt(Metronome m, EventArgs e) 
    { 
    System.Console.WriteLine("HEARD IT"); 
    } 

}, प्रतिनिधि नहीं

अपने कोड m.Tick + = वहीं

आप उस हिस्से को देखने को देखने के

1

आप अपने कार्यक्रम आप घटना जोड़ने के लिए एक श्रोता जोड़ते हैं क्या आप संपत्ति (प्रकार की घटना) के लिए पूछ रहे हैं और आप इसे + = के साथ श्रोता जोड़ रहे हैं। अब आप केवल उस टिक संपत्ति को टिक टिकैंडर प्रकार में जोड़ सकते हैं और यदि आप इसे ओवरराइड करते हैं तो आपको अपना खुद का बनाना होगा जो टिकहैंडलर जैसा ही प्रारूप है।

जब आप स्ट्रिंग या int में जोड़ते हैं तो उतना ही अधिक।

string stringTest = string.Empty; 
stringTest += "this works"; 
stringTest += 4; //this doesn't though 
int intTest = 0; 
intTest += 1; //works because the type is the same 
intTest += "This doesn't work"; 
Metronome m = new Metronome(); 
Metronome.TickHandler myTicker = new Metronome.TickHandler(function); 
m.Tick += myTicker; //works because it is the right type 
m.Tick += 4; //doesn't work... wrong type 
m.Tick += "This doesnt work either"; //string type is not TickHandler type 

क्या यह कुछ साफ़ करता है?

+0

आप मुझे बताएं कि प्रतिनिधि के बारे में सुरक्षित है। लेकिन प्रतिनिधि और घटना के बीच मुझे अंतर मत बताओ। क्या आप मुझे और अधिक बता सकते हैं ? – hqt

1

जहां तक ​​मैं सूचित कर रहा हूँ एक घटना मूल रूप से एक बहुस्त्र्पीय प्रतिनिधि है, लेकिन बुनियादी कार्यों के लिए विभिन्न पहुँच नियम, कि भीतर या बाहर क्लास में उन्हें परिभाषित कर रहे हैं के प्रतिनिधियों और घटनाओं पर किया जा सकता है।

संचालन कर रहे हैं: का उपयोग कर

असाइन = ऑपरेटर

जोड़ें/का उपयोग कर हटाने + = और - = ऑपरेटर

आह्वान() ऑपरेटर

का उपयोग कर
   Operation   | delegate | event 
       ------------------+------------+-------- 
Inside class +=/-=   | valid  | valid 
       ------------------+------------+-------- 
Inside class =     | valid  | valid 
       ------------------+------------+-------- 
Inside class ()    | valid  | valid 
       ------------------+------------+-------- 
Outside class +=/-=   | valid  | valid 
       ------------------+------------+-------- 
Outside class =    | valid  | not valid 
       ------------------+------------+-------- 
Outside class ()    | valid  | not valid 

यह आपको encapsulation देता है जो हमेशा अच्छी ओओपी शैली है। :-)

+0

नहीं, एक घटना * मल्टीकास्ट प्रतिनिधि नहीं है, संपत्ति से कहीं अधिक एक क्षेत्र है। –

+1

@ जोनस्केट: एमएसडीएन (http://msdn.microsoft.com/en-us/library/8627sbea(v=vs.100).aspx) कहता है: घटनाएं एक विशेष प्रकार का मल्टीकास्ट प्रतिनिधि है जो केवल भीतर से ही बुलाया जा सकता है कक्षा या संरचना जहां उन्हें घोषित किया जाता है (प्रकाशक वर्ग)। किसी ऐसे व्यक्ति के लिए जो सी # में गहरा है, वह काफी उथला है! – Mithrandir

+0

एमएसडीएन बस * गलत * है। (यह पहली बार नहीं है।) एक घटना * एक * प्रतिनिधि नहीं है। यह एक सदस्य प्रकार है जो प्रतिनिधियों को सब्सक्राइब करने या हटाने की अनुमति देता है। (घटना का कार्यान्वयन कक्षा तक है।) क्या आपको लगता है कि स्ट्रिंग प्रॉपर्टी स्ट्रिंग के समान है? यह एक समान स्थिति है। यह एक शर्म की बात है कि एमएसडीएन यहां गलत है, लेकिन इसे प्रसारित करने की कोई आवश्यकता नहीं है ... सी # विनिर्देश (सी # 4 स्पेक का सेक्शन 10.8) अधिक सटीक रूप से शुरू होता है - मेरा सुझाव है कि आप इसे पढ़ लें। –

3

"event" एक संशोधक है। क्या फायदा है?

  1. आप इंटरफेस
  2. में घटनाओं का उपयोग केवल वर्ग की घोषणा यह एक घटना
  3. घटनाओं आह्वान कर सकते हैं एक add और remove एक्सेसर है कि आप को ओवरराइड और कस्टम सामान कर सकते हैं बेनकाब कर सकते हैं
  4. घटनाओं एक करने के लिए आप को सीमित असाइन किए गए विधि SomeMethod(object source, EventArgs args) का विशिष्ट हस्ताक्षर जो आपको ईवेंट के बारे में अतिरिक्त जानकारी प्रदान करता है।
+1

मैं यह नहीं कहूंगा कि यह एक संशोधक है। यह एक कीवर्ड है, लेकिन यह एक अलग प्रकार के सदस्य - एक घटना शुरू करने के लिए है। उस बिंदु पर, यह एक कार्यक्रम घोषणा है, एक फील्ड घोषणा नहीं। एक फ़ील्ड जैसी घटना घोषणा * * एक फ़ील्ड पेश करती है, लेकिन यह एक कार्यान्वयन विस्तार है। –