2010-03-17 42 views
81

Tôi hiện đang có một trang được khai báo như sau:Sử dụng biểu thức lambda cho xử lý sự kiện

public partial class MyPage : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     //snip 
     MyButton.Click += (o, i) => 
     { 
      //snip 
     } 
    } 
} 

Tôi chỉ vừa mới chuyển đến NET 3.5 từ 1.1, vì vậy tôi sử dụng để quản lí sự kiện bên ngoài của Page_Load. Câu hỏi của tôi là; có bất kỳ hạn chế hiệu suất hoặc cạm bẫy tôi nên xem ra khi sử dụng phương pháp lambda cho điều này? Tôi thích nó, vì nó chắc chắn ngắn gọn hơn, nhưng tôi không muốn hy sinh hiệu suất để sử dụng nó. Cảm ơn.

Trả lời

81

Không có tác động về hiệu suất vì trình biên dịch sẽ dịch biểu thức lambda của bạn thành một đại biểu tương đương. Các biểu thức lambda không có gì khác ngoài một tính năng ngôn ngữ mà trình biên dịch dịch thành mã chính xác mà bạn đang sử dụng để làm việc.

Trình biên dịch sẽ chuyển đổi mã bạn có một cái gì đó như thế này:

public partial class MyPage : System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     //snip 
     MyButton.Click += new EventHandler(delegate (Object o, EventArgs a) 
     { 
      //snip 
     }); 
    } 
} 
+0

Tôi hiểu. Vì vậy, cũng không có nhược điểm từ việc có các trình xử lý bên trong Page_Load so với việc có chúng bên ngoài nó? –

+1

Quy ước hiện hành là gắn các trình xử lý sự kiện vào phương thức 'OnInit' nhưng vì sự kiện' Click' của nút sẽ được nâng lên sau khi trang tải ví dụ này là tốt. –

+6

Điều quan trọng cần lưu ý là không giữ lại tham chiếu đến đại biểu, bạn không thể hủy đăng ký khỏi sự kiện. – snarf

2

Không tác động hiệu suất mà tôi biết hoặc có bao giờ chạy vào, như xa như tôi biết chỉ là "đường cú pháp" của nó và biên dịch thành điều tương tự như sử dụng cú pháp đại biểu, v.v.

42

Hiệu suất khôn ngoan giống như phương pháp được đặt tên. Vấn đề lớn là khi bạn làm như sau:

MyButton.Click -= (o, i) => 
{ 
    //snip 
} 

Nó có thể sẽ cố gắng loại bỏ một lambda khác, để nguyên bản gốc ở đó. Vì vậy, bài học là nó là tốt, trừ khi bạn cũng muốn có thể loại bỏ các xử lý.

+2

"Nó sẽ * có thể * cố gắng ..."? Nó sẽ * bao giờ * loại bỏ xử lý chính xác trong một tình huống như vậy? –

+1

@ O.R.Mapper: Nếu lambda chụp một biến, nó không thể loại bỏ trình xử lý chính xác. Trong các trường hợp khác, nó tùy thuộc vào trình biên dịch. – Gabe

+0

Thật sao? Thú vị - vì vậy, nếu tôi đăng ký hai hàm ẩn danh trông giống nhau (wlog có một phần trống), và sau đó tôi hủy đăng ký (sử dụng '- =') một hàm ẩn danh khác có thân trống, về cơ bản là không xác định hai trình xử lý sự kiện sẽ bị xóa hoặc liệu có bất kỳ trình xử lý sự kiện nào bị xóa không? –

28
EventHandler handler = (s, e) => MessageBox.Show("Woho"); 

button.Click += handler; 
button.Click -= handler; 
+1

Thông tin rất hữu ích, mặc dù nó tắt chủ đề (câu hỏi về hiệu suất). –

+2

Không chính xác ngoài chủ đề vì việc sử dụng bộ nhớ có thể dẫn đến hạ cấp hiệu suất. – Vladius

+1

Việc xóa chính nó trong trình xử lý cũng có thể hữu ích: '' 'C# EventHandler handler = null; handler = (s, e) => {MessageBox.Show ("Woho"); button.Click - = handler;} '' ' – Vladius

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