2010-08-17 13 views
9

मैं सी # 3.0 का उपयोग कर रहा हूं। मानक घटना पैटर्न के बाद मेरे पास है:क्या मेरी कक्षा अपनी सार्वजनिक घटनाओं की सदस्यता लेनी चाहिए?

public event EventHandler<EventArgs> SomeEventHappens; 

    protected virtual void OnSomeEventHappens(EventArgs e) 
    { 
     if (SomeEventHappens != null) 
     { 
      SomeEventHappens(this, e); 
     } 
    } 

    private object _someProperty; 

    public object SomeProperty 
    { 
     get 
     { 
      return _someProperty; 
     } 
     private set 
     { 
      if (_someProperty == value) 
      { 
       return; 
      } 
      OnSomeEventHappens(EventArgs.Empty); 
      _someProperty = value; 
     } 
    } 

मेरी एक ही कक्षा के भीतर मैं कुछ कार्रवाई जब SomeProperty परिवर्तन लेना चाहते हैं।

1) मेरी SomeProperty सेटर के भीतर सामान कार्य करें: जिस तरह से मैं इसे देख रहा 3 विकल्प है। ऐसा करने के बारे में मुझे कुछ गलत तरीका है क्योंकि मैं सबकुछ के दर्शन की सदस्यता लेने की कोशिश करता हूं, एक चीज करना चाहिए और इसे अच्छी तरह से करना चाहिए। एक सेटर में क्रैमिंग सामान उस के खिलाफ जाना प्रतीत होता है, या कम से कम प्रवृत्ति है।

2) OnSomeEventHappens में सामान करें। फिर, यह सरल टुकड़ों में रखने के खिलाफ थोड़ा सा लगता है। साथ ही, यदि यह विधि ओवरराइड हो जाती है, तो कार्यान्वयनकर्ता मूल विधि को कॉल नहीं करता है, तो संभावित रूप से कार्यक्षमता खो सकता है।

3) कक्षा SomeEventHappens की सदस्यता लें। मेरे लिए यह उचित विकल्प लगता है जहां तक ​​encapsulation का संबंध है, और बहुत साफ लगता है। फिर, OnSomeEventHappens पर संभावित प्रतिक्रियाएं ओवरराइड हो गई हैं।

शायद कुछ और सुरुचिपूर्ण है? मैं विकल्प 2 और 3 के बीच फैसला नहीं कर सकता, और मैं उत्सुक हूं कि सर्वश्रेष्ठ अभ्यास क्या है। हो सकता है कि सबसे सुरक्षित स्थान संपत्ति सेटटर में सभी के बाद हो।

विचार?

अद्यतन: नीचे दी गई महान टिप्पणियों और उत्तरों के लिए धन्यवाद। मैंने सीखा है कि कक्षा अपने स्वयं के कार्यक्रमों की सदस्यता लेने के लिए "ठीक है", हालांकि मेरे मामले में मैं ओवरहेड के कारण नहीं करने के लिए झुका रहा हूं। मैंने अपने आभासी तरीकों के संभावित ओवरडर्स के व्यवहार में क्या विचार किया है और मैं वास्तव में क्या करना चाहता हूं।

मेरे असली दुनिया के मामले में, मैं वास्तव में संपत्तियों को सेट किए बिना घटनाओं को उठाना नहीं चाहता हूं। जैसा कि नीचे दिए गए उत्तरों ने मेरी विचार प्रक्रिया को निर्देशित किया है, मुझे लगता है कि मैं निचले ओवरहेड के कारण विकल्प 1 के साथ जा सकता हूं, विरासतकर्ताओं से अनुचित व्यवहार का कम जोखिम, और यह आम तौर पर मुझे बेहतर समझ में आता है। एक बार फिर धन्यवाद!

उत्तर

2

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

+0

मैंने यह जवाब चुना क्योंकि यह मेरे द्वारा किए जाने वाले कार्यों के निकटतम स्पष्टीकरण था। मैंने आपको अन्य उत्तरों से बहुत कुछ सीखा। धन्यवाद! –

1

क्या आप हमेशा यह कार्रवाई करना चाहते हैं, या आप सदस्यता लेना चाहते हैं और सदस्यता छोड़ना चाहते हैं? बाद के मामले में, विकल्प 3 स्पष्ट रूप से एक अच्छा विचार है।

क्या आप जिस कार्रवाई को पर लेना चाहते हैं, जो एक और वर्ग लेना चाहते हैं? फिर, उस विकल्प 3.

की ओर झुक जाएगा कार्रवाई आप संपत्ति स्थापित करने का स्वाभाविक भाग लेना चाहते है? यदि ऐसा है, तो कार्रवाई 1 सलाह दी जा सकती है।

विकल्प 3 मेरे लिए एक अच्छा "हल्का स्पर्श" दृष्टिकोण जैसा लगता है।

+0

मेरी असली दुनिया की स्थिति में (उपर्युक्त संस्करण ऊपर नहीं) मैं सदस्यता लेना और सदस्यता समाप्त नहीं करना चाहता हूं। संपत्ति वास्तव में एक enum है और enum मूल्य सेट के आधार पर विभिन्न घटनाओं में से किसी एक को उठाया जाता है। चूंकि मैं सेटर में घटना को बढ़ा रहा हूं, इसलिए सभी घटना की जानकारी मेरे लिए उपलब्ध है। ओवरहेड-वार, उन सभी घटनाओं की सदस्यता लेने के लिए हल्का हो सकता है और बस इसे सेटटर में सौदा कर सकते हैं। –

2

नेट के बाहर वस्तु चौखटे में, एक उद्देश्य यह है कि अपनी ही घटनाओं का सदस्य बनता इसका मुख्य कारण ऐसी बातें वृत्तीय संदर्भ उस वस्तु को अनिश्चित काल के जीवित रख सकता है के लिए नेतृत्व पर सिकोड़ी है। यह कोई मुद्दा नहीं है।नेट, लेकिन यह अभी भी एक वस्तु के लिए खुद को पकड़ने के लिए "अजीब" लगता है।

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

यदि आपको कभी-कभी संपत्ति बदलने पर सूचित होने की आवश्यकता होती है, तो मुझे लगता है कि घटना की सदस्यता लेना और सदस्यता रद्द करना उचित होगा।

+0

मेरा प्रारंभिक विचार यह था कि संभवतः यह वर्ग के लिए स्वयं सदस्यता लेने के लिए भी तैयार हो गया था। कुछ अन्य उत्तरों और आपके कुछ से यह .NET में कोई समस्या नहीं प्रतीत होता है। अगर मैं अपने ऑनसोमवेन्ट हैप्पन वर्चुअल विधि में कुछ अतिरिक्त तर्क डालता हूं, तो मुझे विश्वास की छलांग लगनी होगी कि ओवरड्रिडर अपने ओवरराइड में मूल संस्करण को कॉल करेंगे। मेरे उद्देश्यों के लिए मैं अभी भी बहस कर रहा हूं कि यह एक मुद्दा होगा या नहीं। –

+1

आभासी और घटनाओं के बीच मुख्य अंतर यह है कि इवेंट हैंडलर को क्या करना चाहिए, इस पर घटनाओं को कम या कोई मांग नहीं है, जबकि वर्चुअल आंतरिक रूप से संविदात्मक हैं। यह हमेशा ऐसा होता है कि वर्चुअल विधि को दस्तावेज किया जाना चाहिए कि यह वर्णन करने के लिए कि कब और क्या यह व्यवहार को विस्तारित या ओवरराइड करते समय वंश द्वारा बुलाया जाना चाहिए। IOW, यदि आपके ओवरड्रिडर अच्छे प्रोग्रामर हैं, तो यह एक प्रमुख चिंता नहीं होनी चाहिए। यदि आपके ओवरडर्स सामान्य सार्वजनिक/यादृच्छिक बेवकूफ होंगे, तो किले की आवश्यकता हो सकती है। – dthorpe

+0

99% मौका है कि कोई ओवरराइडर मेरा भविष्य का होगा, चाहे वह मुझे अच्छे प्रोग्रामर या यादृच्छिक बेवकूफ की श्रेणी में डाल दे, बहस के लिए! :) –

1

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

private object _someProperty; 
    public object SomeProperty 
    { 
     get 
     { 
      return _someProperty; 
     } 
     private set 
     { 
      if (_someProperty != value) 
      { 
       OnSettingSomeProperty(_someProperty, value); 
       OnSomeEventHappens(EventArgs.Empty); 
       _someProperty = value; 
      } 
     } 
    } 

    protected virtual void OnSettingSomeProperty(object oldValue, object newValue) 
    { 
     // children can play here, validate and throw, etc. 
    } 
+0

यह विकल्प 1 पर झुकाव करने के लिए वापस चला जाता है। हालांकि मुझे नहीं लगता कि मैं ऑनसेटिंग सोमप्रोपर्टी वर्चुअल, शायद निजी बनाउंगा, इसलिए मैं गारंटी दे सकता हूं कि इसे याद नहीं किया जाएगा। मुझे ऐसी स्थितियों की तुलना में घटना के बारे में कम ख्याल है जो इसे पहले स्थान पर उठाया गया था। –

+0

@jomtois, 'ऑनसेटिंग सोमप्रोपर्टी' का इरादा वंशजों को व्यवहार को इंजेक्ट करने की अनुमति देना है। यह स्पष्ट है कि आपके पास क्या है लेकिन आप अपनी मूल पोस्ट में क्या नहीं चाहते हैं। शायद आप किसी के जवाब से खुश नहीं हैं क्योंकि आपने अपने प्रश्न में 'सामान ...' को परिभाषित नहीं किया है। – Marc

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