2012-04-05 22 views
11

मैं थोड़ी सी सी # के लिए नया हूं, इसलिए मैं इस समस्या के साथ आया। प्रश्न: func2 क्यों कहा जाता है? ओह, और एक और बात। कहते हैं कि मैं एक प्रतिनिधि को एक समारोह जोड़ता हूं। इस फ़ंक्शन में मैं एक और प्रतिनिधि को कॉल करता हूं, हालांकि मैं यह सुनिश्चित करना चाहता हूं कि पहले प्रतिनिधि को जोड़ा गया हर दूसरे फ़ंक्शन को इस प्रतिनिधि को कॉल करने से पहले कहा जाता है, क्या कोई साफ समाधान है (वास्तव में getInvocationList में दिलचस्पी नहीं है)। धन्यवाद दोस्तों, आप सबसे अच्छे हैं।सी # प्रतिनिधि काम नहीं कर रहा है?

class Program 
{ 
    delegate void voidEvent(); 
    voidEvent test; 

    private void func1() 
    { 
     Console.Write("func1"); 
     test -= func2; 
    } 

    private void func2() 
    { 
     Console.WriteLine("func2"); 
    } 

    static void Main(string[] args) 
    { 
     Program p = new Program(); 
     p.test += p.func1; 
     p.test += p.func2; 
     p.test(); 
    } 
} 

उत्तर

21

हर बार जब आप एक प्रतिनिधि को बदलने (+ = या - =), आप प्रभावी रूप से मंगलाचरण सूची की एक पूरी कॉपी (तरीकों कि कहा जाता हो जाएगा) बना रहे हैं।

उस वजह से, जब आप p.test(); पर कॉल करते हैं, तो आप पर उस बिंदु पर आमंत्रण सूची में प्रत्येक प्रतिनिधि को आमंत्रित करने जा रहे हैं। उन हैंडलर में से किसी एक के अंदर इसे बदलने से इसे अगले कॉल के लिए बदल दिया जाएगा, लेकिन वर्तमान में निष्पादित कॉल को नहीं बदलेगा।

+3

+1। हाँ। यही कारण है कि आप 'var func = p.test लिख सकते हैं; अगर (func! = null) {func(); } 'कुछ भी लॉक किए बिना multithreading परिदृश्य में। चूंकि 'func'' p.test' की एक प्रति है और 'p.test' में किए गए परिवर्तनों की परवाह नहीं करता है। –

+0

लेकिन जब मैं test- = func2 कॉल करता हूं और getinvocationlist पर कॉल करता हूं तो मैं देख सकता हूं कि func2 सूची में और नहीं है। तो आप कह रहे हैं कि प्रत्येक प्रतिनिधि के पास दो सूचियां हैं, जिन्हें वर्तमान में बुलाया जा रहा है (और पहुंच योग्य नहीं है) और एक जिसे अगली बार बुलाया जाएगा? – Yamcha

+0

@ user1316459, इसमें वास्तव में दो सूचियां नहीं हैं। लेकिन जब आप दायर से प्रतिनिधि का आह्वान करते हैं, तो आप प्रभावी रूप से कुछ ऐसा कहते हैं: "फ़ील्ड का मान * अभी * लें और फिर उसे आमंत्रित करें"। इसका मतलब है कि आप 'test' के मान की प्रतिलिपि बना रहे हैं, न कि' test'। – svick

8

रीड बिल्कुल सही है। इसके बारे में सोचने का एक और तरीका यहां है।

class Number 
{ 
    public static Number test; 
    private int x; 
    public Number(int x) { this.x = x; } 
    public Number AddOne() 
    { 
     return new Number(x + 1); 
    } 
    public void DoIt() 
    { 
     Console.WriteLine(x); 
     test = test.AddOne(); 
     Console.WriteLine(x); 
    } 
    public static void Main() 
    { 
     test = new Number(1); 
     test.DoIt(); 
    } 
} 

क्या यह 1, 1, या 1, 2 प्रिंट करना चाहिए? क्यूं कर?

यह 1 प्रिंट चाहिए, 1. जब आप कहते हैं कि

test.DoIt(); 

कि

 Console.WriteLine(test.x); 
     test = test.AddOne(); 
     Console.WriteLine(test.x); 

मतलब यह नहीं है! बल्कि, इसका मतलब है कि

Number temporary = test; 
Console.WriteLine(temporary.x); 
test = test.AddOne(); 
Console.WriteLine(temporary.x); 

testका मूल्य बदलने छदाम में this का मूल्य नहीं बदलता है।

आप वही काम कर रहे हैं। test के मान को बदलना आपके द्वारा आमंत्रित किए जा रहे कार्यों की सूची को नहीं बदलेगा; आपने बुलाए जाने वाले कार्यों की एक विशेष सूची और की मांग की है कि सूची लागू की जा रही है। आपको विधि कॉल के माध्यम से this आधे रास्ते का अर्थ बदलने के अलावा, इसे आधे रास्ते में बदलने के लिए नहीं मिलता है।

+1

आपको 'संख्या' की परिभाषा में फ़ील्ड' x' दिखाई दे रहा है। – kvb

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