2011-04-02 15 views
6
public virtual void OnRegistrationJoin(RegistrationJoinEventArgs e) 
{ 
    foreach (Mobile member in e.Team) 
    { 
     member.SendMessage(1161, "You join the {0}.", EventFullName); 

     if (e.Team.Count > 1) 
     { 
      Joinees.Remove(member); 
      member.SendMessage(1161, "Your team formation is:"); 

      int i = 0; 

      foreach (Mobile parter in e.Team.Where(partner => partner != member).ToList()) 
      { 
       member.SendMessage(1150, "{0}: {1}.", ++i, partner.Name); 
      } 
     } 
    } 

    Members.Add(e.Team); 
} 

मुझे रिशेर्पर द्वारा "संशोधित बंद करने की अनुमति" तक पहुंच मिलती है, मैं सोच रहा था कि इस कोड के साथ क्या गलत है, क्योंकि मैं आंतरिक लूप में जो कुछ करता हूं वह एक संदेश भेजता है?सी # संशोधित बंद करने के लिए

+1

संभावित संशोधित [संशोधित बंद करने के लिए एक्सेस] (http://stackoverflow.com/questions/235455/access-to-modified-closure) और कई अन्य संभावित डुप्लिकेट। – adrianbanks

उत्तर

13

समस्या में है में प्रयोग किया जाता चर संशोधित है संशोधित कर सकते हैं:

e.Team.Where(partner => partner != member) 

चर membermember चर के लिए एक सीधा संदर्भ है बाहरी दायरे में। जबकि आपको उपर्युक्त कोड में कोई समस्या नहीं हो सकती है, तो जब आप एकाधिक धागे पर कोड चला रहे हैं या Where विधि में लैम्ब्डा का मूल्यांकन नहीं कर रहे हैं तो यह समस्याग्रस्त है (उदाहरण के लिए, IEnumerable के बजाय IQueryable का उपयोग करना)।

कारण यह एक समस्या है कि सी # Where पर एक प्रतिनिधि के रूप में पास करने के लिए एक विधि उत्पन्न करता है। उस विधि को memeber तक सीधे पहुंच की आवश्यकता है। आप इस तरह से एक और वेरिएबल का संदर्भ देने वाले हैं:

var m = member; 
// ... 
e.Team.Where(partner => partner != m); 

तो सी # कि मूल्य "पर कब्जा" कर सकते हैं एक निर्माण एक "बंद" कहा जाता है और यह उत्पन्न विधि से गुजरती हैं। इससे यह सुनिश्चित होगा कि member परिवर्तनों के बाद, जब आप इसे Where पर पास करते हैं तो वह मान बदलता नहीं है।

+0

+1: अंततः अधिकांश लोगों के लिए जो सबसे बड़ी समस्याएं आ रही हैं, वह स्थगित निष्पादन है। – vcsjones

+0

आसानी से var closureMember = सदस्य कर तय किया गया है। और LINQ में बंदरगाह का उपयोग कर। –

+0

@ फेमेरेफ - लेकिन यह बदल रहा संदर्भ है कि समस्या है, बदलते उदाहरण नहीं। – codekaizen

0

मुझे लगता है member.SendMessagemember

कि एक बंद लैम्ब्डा

+0

वास्तव में नहीं। समस्या बाहरी foreach पाश है जो लैम्ब्डा में बाध्य 'सदस्य' चर को संशोधित करता है। – Femaref

2

भाग पुनर्विक्रेता e.Team.Where(partner => partner != member).ToList() के बारे में शिकायत करता है, संदर्भित member बदलेगा। इस मामले में, यह कोई समस्या नहीं है, लेकिन अन्य मामलों में, यह एक समस्या हो सकती है।

नोट: आपको ToList() का उपयोग करने की आवश्यकता नहीं है, जो IEnumerable<T> के उत्सुक मूल्यांकन को मजबूर करता है। बस e.Team.Where(partner => partner != member) से अधिक सक्रिय करें।

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

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