2012-06-24 28 views
92

myDelegate -= eventHandler ReSharper (6 संस्करण) मुद्दों का उपयोग करते समय:"रेसर्पर/सी # में" प्रतिनिधि घटाव का अप्रत्याशित परिणाम है "?

प्रतिनिधि घटाव अप्रत्याशित परिणाम

तर्कसंगत इसके पीछे explained by JetBrains here है। स्पष्टीकरण समझ में आता है और, इसे पढ़ने के बाद, मैं प्रतिनिधियों पर - के अपने सभी उपयोगों पर संदेह कर रहा हूं।

कैसे तो,

  • मैं ReSharper गुस्सैल बनाने के बिना एक गैर ऑटो घटना लिख ​​सकता है?
  • या, क्या इसे लागू करने के लिए एक बेहतर और/या "सही" तरीका है?
  • या, क्या मैं बस रीशेपर को अनदेखा कर सकता हूं?

यहाँ सरल है कोड:

public delegate void MyHandler (object sender); 

MyHandler _myEvent; 

public event MyHandler MyEvent 
{ 
    add 
    { 
     _myEvent += value; 
     DoSomethingElse(); 
    } 
    remove 
    { 
     _myEvent -= value; // <-- ReSharper warning here 
    } 
} 
+0

मोनो एक ही चेतावनी देता है। यहां समस्या का आर # का विवरण है https://confluence.jetbrains.com/display/ReSharper/Delegate+subtraction+has+unpredictable+semantics (जो केवल प्रतिनिधियों की सूचियों पर लागू होता है) – thoredge

उत्तर

107

डरो मत! ReSharper की चेतावनी का पहला भाग केवल प्रतिनिधियों की सूचियों को हटाने पर लागू होता है। आपके कोड में, आप हमेशा एक प्रतिनिधि को हटा रहे हैं। डुप्लिकेट प्रतिनिधि को हटा दिए जाने के बाद दूसरे भाग प्रतिनिधियों के आदेश के बारे में बात करते हैं। एक कार्यक्रम अपने ग्राहकों के लिए निष्पादन के आदेश की गारंटी नहीं देता है, इसलिए यह वास्तव में आपको प्रभावित नहीं करता है।

चूंकि उपर्युक्त यांत्रिकी अप्रत्याशित परिणामों का कारण बन सकती है, इसलिए जब भी यह एक प्रतिनिधि घटाव ऑपरेटर से मुकाबला करता है तो रीशेपर चेतावनी जारी करता है।

रीशेपर इस चेतावनी जारी कर रहा है क्योंकि मल्टीकास्ट प्रतिनिधि घटाव में गॉथस हो सकता है, यह पूरी तरह से उस भाषा सुविधा की निंदा नहीं कर रहा है। सौभाग्य से उन गेटचास फ्रिंज मामलों में हैं और यदि आप सरल घटनाओं का उपयोग कर रहे हैं तो आप उन्हें सामना करने की संभावना नहीं रखते हैं। अपने add/remove हैंडलर को लागू करने का कोई बेहतर तरीका नहीं है, आपको केवल नोटिस लेना होगा।

मैं उस संदेश के लिए "संकेत" के लिए रीशेर्पर के चेतावनी स्तर को डाउनग्रेड करने का सुझाव देता हूं ताकि आप उनकी चेतावनियों के लिए निराश न हों, जो आमतौर पर उपयोगी होते हैं।

+0

मुझे थोड़ा कम स्क्वैमिश लग रहा है पहले से ही :) –

+51

मुझे लगता है कि परिणाम "अप्रत्याशित" कहने के लिए आर # का बुरा है। वे बहुत स्पष्ट रूप से निर्दिष्ट हैं। "उपयोगकर्ता भविष्यवाणी नहीं कर सकता" किसी भी तरह से "अप्रत्याशित" जैसा नहीं है। (यह भी कहना गलत है कि .NET ढांचा ओवरलोड को परिभाषित करता है - यह सी # कंपाइलर में बेक किया गया है। 'प्रतिनिधि * * * अधिभार '+' और '-'।) –

+6

@ जोन: मैं सहमत हूं। मुझे लगता है कि हर किसी को उच्च बार माइक्रोसॉफ्ट के लिए इस्तेमाल किया गया है। पॉलिश का स्तर उतना ही ऊंचा है जितना कि .NET दुनिया में इतनी सारी चीजें हैं जो आपको "सफलता के गड्ढे में गिरती हैं", एक भाषा सुविधा का सामना करना पड़ती है जो कि गड्ढे के बगल में एक तेज चलना है जहां एक है मौका आपको याद आ सकता है कि कुछ लोगों को झटके लगने और एक संकेत देने का वादा किया जाता है कि 'सफलता का पीट यह है --->'। –

-13

सेट यह = बातिल के बजाय का उपयोग करने - =

+3

किसी ईवेंट की 'निकालें' विधि को सभी हैंडलर को नहीं हटाया जाना चाहिए, बल्कि हैंडलर को निकालने का अनुरोध किया गया था। – Servy

+0

अगर वह केवल एक जोड़ा गया है तो अगर वह केवल एक को हटा देता है तो उसने उन्हें हटा दिया है। मैं सिर्फ इस विशिष्ट रिशेर्पर संदेश के लिए सभी मामलों में इसका उपयोग नहीं कर रहा हूं। –

+3

लेकिन आप * नहीं जानते * प्रतिनिधि हमेशा आमंत्रण सूची पर एकमात्र आइटम निकाल रहा है। यह सही काम करने वाले कोड को गलत टूटे हुए कोड में बदलकर रिशेर्पर संदेश को दूर कर रहा है, जो कुछ परिस्थितियों में संयोग से काम करेगा, लेकिन यह कई मामलों में तरीकों का निदान करने के लिए असामान्य और कठिन हो जाएगा। – Servy

9

आप सीधे योग या घटाना प्रतिनिधियों उपयोग नहीं करना चाहिए। इसके बजाय आपका क्षेत्र

MyHandler _myEvent; 

इसके बजाय एक ईवेंट के रूप में भी घोषित किया जाना चाहिए। यह आपके समाधान को जोखिम के बिना समस्या का समाधान करेगा और अभी भी घटना के उपयोग का लाभ होगा।

event MyHandler _myEvent; 

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

myObject.MyEvent += Method1; 
myObject.MyEvent += Method2; 
myObject.MyEvent = Method3; 

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

+0

मैंने कभी ऐसा करने का विचार नहीं किया है, लेकिन जब तक आप उस अंतर्निहित घटना को निजी रखते हैं, तब तक ईवेंट प्रतिनिधि उपयोग की रक्षा करना समझ में आता है। यह तब भी अच्छा काम नहीं करता है जब अधिक विशिष्ट थ्रेड सिंक्रनाइज़ेशन होते हैं जो जोड़/हटाए गए हैंडलर में होना चाहिए जैसे एकाधिक ईवेंट सदस्यता या उप-सदस्यता जिन्हें ट्रैक किया जाना चाहिए। हालांकि, किसी भी मामले में यह चेतावनियों को हटा देता है। – Jeremy