2012-04-05 35 views
11

im kinda mới với C#, vì vậy tôi đã đưa ra vấn đề này. Câu hỏi: tại sao func2 lại được gọi? ồ, và một điều nữa. nói rằng tôi thêm một chức năng cho một đại biểu. Trong hàm này tôi gọi một delegate khác, tuy nhiên tôi muốn đảm bảo rằng mọi hàm khác được thêm vào delegate đầu tiên được gọi trước khi hàm này gọi cho delegate này, có bất kỳ giải pháp sạch (không thực sự quan tâm đến getInvocationList). Xin cảm ơn các bạn, bạn là người giỏi nhất.C# đại biểu không làm việc như nó phải không?

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(); 
    } 
} 

Trả lời

21

Mỗi khi bạn thay đổi một đại biểu (+ = hoặc - =), bạn đang tạo một bản sao toàn bộ danh sách yêu cầu (các phương thức sẽ được gọi).

Do đó, khi bạn gọi p.test();, bạn sẽ gọi mọi đại biểu trong danh sách yêu cầu tại thời điểm đó. Thay đổi điều này bên trong một trong những trình xử lý đó sẽ thay đổi nó cho cuộc gọi tiếp theo, nhưng sẽ không thay đổi cuộc gọi hiện đang thực hiện.

+3

+1. Vâng. Đây là lý do tại sao bạn có thể viết 'var func = p.test; if (func! = null) {func(); } 'trong kịch bản đa luồng mà không khóa bất cứ thứ gì. Bởi vì 'func' là một bản sao của' p.test' và không quan tâm đến những thay đổi được thực hiện cho 'p.test'. –

+0

nhưng sau khi tôi gọi test- = func2 và gọi getinvocationlist tôi có thể thấy func2 không còn trong danh sách nữa. Vì vậy, bạn đang nói rằng mỗi đại biểu có hai danh sách, một trong đó hiện đang được gọi (và không thể truy cập) và một trong đó sẽ được gọi lần sau? – Yamcha

+0

@ user1316459, nó không thực sự có hai danh sách. Nhưng khi bạn gọi một đại biểu từ một đệ, bạn có hiệu quả nói điều gì đó như: "lấy giá trị của trường * ngay bây giờ * và sau đó gọi đó". Điều đó có nghĩa là bạn đang gọi một bản sao của giá trị của 'test', không phải' test' chính nó. – svick

8

Reed dĩ nhiên là chính xác. Đây là một cách khác để suy nghĩ về nó.

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(); 
    } 
} 

Có nên in 1, 1 hoặc 1, 2 không? Tại sao?

Nó nên in 1, 1. Khi bạn nói

test.DoIt(); 

đó không có nghĩa

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

! Thay vào đó, có nghĩa là

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

Thay đổi giá trị của testkhông làm thay đổi giá trị của this trong DoIt.

Bạn đang làm chính xác điều tương tự. Thay đổi giá trị test không thay đổi danh sách các hàm mà bạn đang gọi; bạn đã yêu cầu một danh sách hàm cụ thể cần gọi và danh sách đó sẽ được gọi. Bạn không thể thay đổi nó nửa chừng, bất cứ điều gì nhiều hơn bạn có thể thay đổi ý nghĩa của this nửa chừng thông qua một cuộc gọi phương thức.

+1

Bạn có vẻ thiếu trường 'x' trong định nghĩa' Số'. – kvb

Các vấn đề liên quan