2013-08-24 35 views
7

Điều này có thể được thực hiện trong vòng lặp for không?Phương pháp ẩn danh cho trình xử lý sự kiện trong vòng lặp

 TickEventArgs targs1 = new TickEventArgs(lbl1_up_time, _elapsedTime_up1); 
     timer_up1.Tick += (sender, e) => Tick(targs1); 

     TickEventArgs targs2 = new TickEventArgs(lbl2_up_time, _elapsedTime_up2); 
     timer_up2.Tick += (sender, e) => Tick(targs2); 

     TickEventArgs targs3 = new TickEventArgs(lbl3_up_time, _elapsedTime_up3); 
     timer_up3.Tick += (sender, e) => Tick(targs3); 

     TickEventArgs targs4 = new TickEventArgs(lbl4_up_time, _elapsedTime_up4); 
     timer_up4.Tick += (sender, e) => Tick(targs4); 

     TickEventArgs targs5 = new TickEventArgs(lbl5_up_time, _elapsedTime_up5); 
     timer_up5.Tick += (sender, e) => Tick(targs5); 

doesnt làm việc này vì tôi là ngoài giới hạn (5)

 targs[0] = new TickEventArgs(lbl1_up_time, _elapsedTime_up1); 
     targs[1] = new TickEventArgs(lbl2_up_time, _elapsedTime_up2); 
     targs[2] = new TickEventArgs(lbl3_up_time, _elapsedTime_up3); 
     targs[3] = new TickEventArgs(lbl4_up_time, _elapsedTime_up4); 
     targs[4] = new TickEventArgs(lbl5_up_time, _elapsedTime_up5); 

     timers[0] = timer_up1; 
     timers[1] = timer_up2; 
     timers[2] = timer_up3; 
     timers[3] = timer_up4; 
     timers[4] = timer_up5; 

     int i = 0; 

     for (i = 0; i <= 4; i++) 
     { 
      timers[i].Tick += (sender, e) => Tick(targs[i]); 
     } 
+0

này được xuất phát từ biểu thức lambda; 'i' được chia sẻ giữa tất cả chúng. Vào thời điểm hàm được thực hiện, chúng chủ yếu được gọi là 'timers [i] .Tick + = (sender, e) => Tick (targs [5])'. Khai báo một địa phương 'int locali = i' và sử dụng nó trong dòng của bạn để thay thế. –

+0

@ChrisSinclair đăng nó làm câu trả lời. – I4V

+0

có thể trùng lặp của [C# Captured Variable In Loop] (http://stackoverflow.com/questions/271440/c-sharp-captured-variable-in-loop) – nawfal

Trả lời

10

Điều này đến từ biểu thức lambda; iis shared between all of them. Vào thời điểm hàm được thực hiện, chúng chủ yếu được gọi là timers[i].Tick += (sender, e) => Tick(targs[5]).

Để tránh điều này, hãy tạo một biến phạm vi cục bộ (int locali = i) và sử dụng biến đó trong dòng của bạn để thay thế. Điều này sẽ đảm bảo rằng mỗi biểu thức lambda thực sự nhận được giá trị bạn mong đợi.

for (i = 0; i <= 4; i++) 
{ 
    int locali = i; 
    timers[locali].Tick += (sender, e) => Tick(targs[locali]); 
} 

i trở thành 5 từ lần lặp cuối cùng của vòng lặp của bạn trước khi thoát. Đương nhiên, bạn không có phần tử targs[5], vì vậy nó ném một số IndexOutOfRangeException.

Về mặt kỹ thuật, bạn không cần sử dụng locali cho phần timers[i].Tick kể từ khi được đánh giá ngay lập tức, nhưng cá nhân tôi cảm thấy khó hiểu khi kết hợp cả hai.


Một số đọc thêm trên concepet:

The foreach identifier and closures

Closing over the loop variable considered harmful

+0

Cảm ơn câu trả lời nhanh. Làm việc như bây giờ. Btw, bạn có biết nếu có một cách để đơn giản hóa việc phân công mảng, tức là tất cả các targs sẽ được thực hiện trong một tuyên bố? – dirtyw0lf

+0

@ dirtyw0lf: Nhưng bạn có tất cả chúng được gán cho các bộ hẹn giờ khác nhau. Bạn có thực sự muốn chỉ một bộ đếm thời gian _single_ để xóa toàn bộ mảng 'targs' không? –

+0

Không, chỉ cần tự hỏi nếu tôi có thể làm điều đó trong một vượt qua cho tất cả các bộ định thời cho việc gán mảng – dirtyw0lf

8

Có chỉ có một i là trong trường hợp này và tất cả các lambdas được chụp cùng giá trị. Sử dụng một địa phương được dàn vào vòng lặp sao cho mỗi lambda có một bản sao khác nhau

for (i = 0; i <= 4; i++) 
{ 
    int j = i; 
    timers[j].Tick += (sender, e) => Tick(targs[j]); 
} 
Các vấn đề liên quan