2009-12-10 16 views
6

उदाहरण के लिए जब आप 'FootballTeam' जैसी कक्षा के विभिन्न उदाहरण हैं और आप इस FootballTeam कक्षा के दूसरे उदाहरण को जानना चाहते हैं कि कुछ हुआ, तो इसके बारे में जाने का सबसे अच्छा तरीका क्या है?सी # कक्षा उदाहरण संचार

घटनाक्रम वास्तव में काम करेंगे नहीं मुझे लगता है कि ...

ईजी:

FootballTeam A = new FootballTeam(); 
FootballTeam B = new FootballTeam(); 

// now A needs to let B know about it's manager change 
// manager is a property inside this class... 
+0

क्या आप किसी वर्ग के सभी उदाहरणों को सूचित करने की कोशिश कर रहे हैं जो कुछ हुआ, या एक विशिष्ट उदाहरण? – JasonTrue

+0

केवल विशिष्ट उदाहरण ... कभी-कभी एक –

उत्तर

4

घटनाक्रम काम कर सकता था:

FootballTeam A = new FootballTeam(); 
FootballTeam B = new FootballTeam(); 
A.ManagerChanged += B.OnOtherManagerChanged; 

घटना की परिभाषा - FootballTeam अपने OnManagerChanged प्रणाली को बुलाती है अपने Manager गुण परिवर्तन मूल्य जब:

class FootballTeam 
{ 
    public event EventHandler ManagerChanged; 

    protected virtual void OnManagerChanged(EventArgs e) 
    { 
     EventHandler handler = ManagerChanged; 
     if (handler != null) 
      handler(this, e); 
    } 

    public void OnOtherManagerChanged(object sender, EventArgs e) 
    { 
     FootballTeam otherTeam = (FootballTeam) sender; 
     // A manager changed on a different FootballTeam instance 
     // ...do something here 
    } 
} 
0

आप Observer pattern इस्तेमाल कर सकते हैं। यह वस्तुओं को उन घटनाओं के लिए "सदस्यता लेने" की अनुमति देता है जिनकी वे परवाह करते हैं।

1

विशिष्ट तरीका नेट में यह करने के लिए है अन्य वस्तुओं के लिए दिलचस्प संचालन के लिए एक घटना को परिभाषित करने के लिए। उदाहरण के लिए आप निम्नलिखित

public class FootballTeam { 
    private string _manager; 
    public string Manager { 
    get { return _manager; } 
    set { 
     if (ManagerChanged != null) { 
     ManagerChanged(this,EventArgs.Empty); 
     } 
    } 
    } 
    public event EventHandler ManagerChanged; 
} 

आदर्श रूप में आप एक अधिक प्रकार सुरक्षित घटना चाहते हैं परिभाषित कर सकता है लेकिन वहाँ केवल इतना यहाँ जगह है

फिर आप अन्य FootballTeam मामलों में इस घटना को सुनने और उस पर प्रतिक्रिया दे सकता घटना।

FootballTeam a = new FootballTeam(); 
FootballTeam b = new FootballTeam(); 
a.ManagerChanged += (sender, e) => { 
    Console.WriteLine("A's manager changed"); 
}; 
1

कुछ अलग तरीके हैं। तथ्य यह है कि आपको ऐसा करने की ज़रूरत है कभी-कभी डिज़ाइन समस्या का संकेत मिलता है, हालांकि निश्चित रूप से व्यावहारिकता खेलना चाहिए। , IDisposable को लागू करने से ईवेंट हैंडलर्स को साफ करने के लिए सुनिश्चित करें

public class FootballTeam 
{ 
    private static event EventHandler SomethingHappened; 

    public FootballTeam() 
    { 
     SomethingHappened += this.HandleSomethingHappened; 
    } 

    public void DoSomething() 
    { 
     SomethingHappened(); //notifies all instances - including this one! 
    } 
} 

एक स्मृति रिसाव से बचने के लिए:

एक आसान तरीका FootballTeam वर्ग जो अपने आप ctor में की सदस्यता में एक निजी स्थिर घटना है :

public class FootballTeam : IDisposable 
{ 
    //... 

    public void Dispose() 
    { 
     SomethingHappened -= this.HandleSomethingHappened; 
     //release the reference to this instance so it can be GC'd 
    } 
} 
+0

एक और सवाल, क्योंकि आप इसे यहां उल्लेख करते हैं, क्या किसी को हमेशा IDISposable का उपयोग करके ईवेंटहेल्डर्स को मैन्युअल रूप से निपटाना पड़ता है? –

+1

नहीं - यह इस मामले में केवल महत्वपूर्ण है क्योंकि घटना स्थैतिक है, इसलिए घटना हमेशा के लिए रहती है और उस उदाहरण के संदर्भ में रहती है जिसमें एक हैंडलर संलग्न होता है। तो उदाहरण जीसीएड कभी नहीं मिलेगा, क्योंकि जीसी देखता है कि अभी भी इसके लिए एक सक्रिय संदर्भ है। जब हम उस समस्या से बचने के लिए किए जाते हैं तो हम संदर्भ को हटा देते हैं। –

+0

इसलिए सामान्य घटनाओं के साथ, इवेंट हैंडलर से स्पष्ट रूप से लागू करने और अनदेखा करने की आवश्यकता नहीं है? –

4

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

अपने उदाहरण में, आप FootballTeam उदाहरणों का वर्णन करते हैं जिन्हें अन्य मामलों में प्रासंगिक परिवर्तन होने पर सूचित किया जाना आवश्यक है। हालांकि, आपको यह तय करना होगा कि FootballTeam वर्ग कीकी जिम्मेदारीहोनी चाहिए ताकि दोनों घटनाओं को सुन सकें और जवाब दे सकें। Single Responsibility Principle बताता है कि कक्षा बदलने के लिए केवल एक कारण होना चाहिए। इस डिजाइन अवधारणा का पालन करने से आमतौर पर चिंताओं और समग्र बेहतर कोड के स्पष्ट पृथक्करण में परिणाम मिलता है।

ऐसी डिज़ाइन में कई समस्याएं उत्पन्न हो सकती हैं।

सबसे पहले, प्रत्येक FootballTeam परिवर्तनों को सुनने और उनके जवाब देने के लिए जिम्मेदार होना जल्दी से समस्याग्रस्त हो सकता है। एक बात के लिए, FootballTeam के बीच प्रत्यक्ष (पॉइंट-टू-पॉइंट) संचार लाइनों की संख्या उदाहरणों की संख्या के वर्ग के साथ बढ़ती है: n * (n-1)। पांच टीमों के साथ आपके पास 20 कनेक्शन होंगे, जिसमें दस टीमों के साथ 90 होगा, तीस टीमों के साथ आपके पास 870 होगा।

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

एक डिजाइन के साथ एक और संभावित समस्या जहां सभी उदाहरण एक-दूसरे पर घटनाओं की सदस्यता लेते हैं, अनंत या चक्रीय घटना श्रृंखला होती है: ए को सूचित करता है, जो खुद को अपडेट करता है और सी को सूचित करता है, जो खुद को अपडेट करता है और ए को सूचित करता है, जो स्वयं अपडेट करता है और अधिसूचित करता है बी ... विज्ञापन infinitum। या जब तक आप ढेर अंतरिक्ष से बाहर नहीं हो जाते। इस तरह के एक डिजाइन में हल करने में यह एक मुश्किल समस्या हो सकती है, और चक्र और रिकर्सन को रोकने के लिए अजीब राज्य प्रबंधन की आवश्यकता होगी।

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

+0

+1 अच्छा स्पष्टीकरण – Simon

+0

इसके लिए कोई उदाहरण कोड या लिंक? – Ujjwal

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