2011-01-20 16 views
5

इससे पहले कभी नहीं आया था।सी #: अभिभावक वर्ग की घटनाओं तक पहुंच संभव नहीं है?

using System; 

namespace Testing 
{ 
    public class Test 
    { 
     public event Action ActionRequired; 
    } 

    public class ChildTest : Test 
    { 
     public void DoSomething() 
     { 
      if (this.ActionRequired != null) 
       this.ActionRequired(); 
     } 
    } 
} 

यह काम नहीं करेगा, त्रुटि मैं केवल आधार वर्ग से घटना का उपयोग कर सकते किया जा रहा है: यहाँ नमूना है।

आसपास यात्रा करना मुश्किल नहीं है (बेस क्लास में एक संरक्षित विधि जोड़ें जो दोनों घटनाओं का आविष्कार जांचता है और उस वर्ग को कक्षा वर्ग से कॉल करता है), लेकिन मुझे आश्चर्य है कि इस प्रतिबंध के पीछे क्या विचार है?

चीयर्स,

सेबी

+0

संभव डुप्लिकेट सी # में बेस क्लास में व्युत्पन्न कक्षाओं में वैसे ही? (http://stackoverflow.com/questions/253757/why-events-cant-be-used-in-the-same-way-in-derived- कक्षा-के-इन-द-बेस-क्लास) –

उत्तर

13

आप वर्ग के भीतर जो वे परिभाषित किया गया के बाहर से घटनाओं आह्वान नहीं कर सकते। हालांकि, आपको इसकी आवश्यकता नहीं है; घटना को आग लगाने के लिए संरक्षित विधि घोषित करने के मूर्खतापूर्ण पिटर का पालन करें।

class Whatever 
{ 
    public event EventHandler Foo; 

    protected virtual void OnFoo(EventArgs e) 
    { 
     EventHandler del = Foo; 
     if(del != null) 
     { 
      del(this, e); 
     } 
    } 
} 

अब वर्ग के वंशज "जो कुछ भी" OnFoo फोन करके ईवेंट को सक्रिय कर सकते हैं() और उचित EventArgs में गुजर आपत्ति है।

संपादित करें: क्यों इस व्यवहार है के संबंध में, जॉन स्कीट यह अच्छी तरह से एक और धागा में विस्तार से बताया है (जो भी मतलब है कि इस सवाल का डुप्लिकेट है, तो बंद करने के लिए मतदान):

जब आप किसी की घोषणा सार्वजनिक क्षेत्र की तरह घटना, संकलक एक सार्वजनिक घटना, और एक निजी क्षेत्र बनाता है। एक ही कक्षा (या नेस्टेड कक्षाओं) के भीतर आप सीधे मैदान पर जा सकते हैं, उदा। सभी हैंडलरों को आह्वान करने के लिए। अन्य कक्षाओं से, आप केवल ईवेंट देखते हैं, जो केवल सदस्यता और सदस्यता रद्द करने की अनुमति देता है।

private Action _actionRequired; 
public event Action ActionRequired 
{ 
    add { _actionRequired += value; } 
    remove { _actionRequired -= value } 
} 

(वास्तविक कोड निश्चित रूप से एक छोटे से अधिक जटिल है)

:

+0

मुझे यह कभी नहीं पता था। जानकारी का अच्छा सा। –

+0

धन्यवाद, यही वह है जो मैंने अभी किया है! –

+0

कोई समस्या नहीं, अधिक जानकारी के लिए इस धागे को देखें: http://stackoverflow.com/questions/253757/why-events-cant-be-used-in-the-same-way-in-derived-classes-as- इन-द-बेस-क्लास # 253803 –

3

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

लेकिन किसी भी अन्य वर्ग से, केवल घटना पहुंच योग्य है, क्षेत्र नहीं। यही कारण है कि आप प्रतिनिधि को किसी अन्य वर्ग, यहां तक ​​कि व्युत्पन्न वर्ग से भी नहीं बुला सकते हैं।

+0

धन्यवाद @ थॉमस जो मुझे यह समझने में मदद करता है कि यह कैसे होता है –

1

पिछले जवाब @ThomasLevesque से जोड़ा https://stackoverflow.com/a/4742280/3926461

आप इस वाक्यात्मक चीनी का उपयोग कर नीचे की तरह बिना अपने कार्रवाई घोषणा कर सकते हैं के अनुसार:

public class Test 
{ 
    protected Action _actionRequired; 
    public event Action ActionRequired { 
     add { 
      _actionRequired += value; 
     } 
     remove { 
      _actionRequired += value; 
     } 
    } 
} 

public class ChildTest : Test 
{ 
    public void DoSomething() 
    { 
     if (this._actionRequired != null) 
      this._actionRequired(); 
    } 
} 
की [क्यों घटनाओं में इस्तेमाल नहीं किया जा सकता
संबंधित मुद्दे