2010-01-29 25 views
8

Ví dụ, tôi có một phương pháp cơ sở xuất bản sự kiện:.NET: Tạo EventArgs mới mỗi lần sự kiện này có thực thi tốt không?

protected virtual OnSomeEvent(EventArgs e) 
    { 
     var handler = SomeEvent; 
     if (handler != null) 
     { 
      handler(this, e); 
      // handler(this, new EventArgs());// EDIT: Yes it should be 
              // handler(this, e), 
              // ignore this one :D 
     } 
    } 

Đối với một lớp được thừa kế đó sẽ ghi đè OnSomeEvent và đặt ra một sự kiện bổ sung khi nó cháy:

protected override OnSomeEvent(EventArgs e) 
    { 
     base.OnSomeEvent(e); 

     if (ExtendedEvent != null) 
     { 
      OnExtendedEvent(e); 
     } 
    } 

    protected void OnExtendedEvent(EventArgs e) 
    { 
     // some stuff done 
     // new information the ExtendedEventArgs object needs 
     // is not available until this point 

     ExtendedEvent(this, new ExtendedEventArgs(someStuff, someOtherStuff)); 
    } 

Và nếu nguồn gốc tiếp tục như thế này , nó sẽ tạo ra một EventArgs có nguồn gốc mới cho mỗi thế hệ của lớp dẫn xuất yêu cầu nó. Tuy nhiên có vẻ như dẫn xuất khác nhau của EventArgs trên khuôn khổ .NET không được thiết kế để có thể thay đổi (không có setters), điều này ngăn cản một đối tượng từ giữ một trường hợp duy nhất của EventArgs và sửa đổi nó khi nó đi.

Vì vậy, mỗi khi một sự kiện như thế này xảy ra, nó sẽ cấp phát lại bộ nhớ cho tất cả các đối tượng EventArgs có liên quan. Trong một ứng dụng đồ họa dữ dội nơi một sự kiện có thể được kích hoạt hàng chục lần mỗi giây (chẳng hạn như OnPaint sự kiện trên một điều khiển), đây thực sự là một thực hành tốt?

Tôi có nên thực hiện một số thay đổi cho OnExtendedEvent() và làm cho ExtendedEventArgs có thể thay đổi được không?

protected ExtendedEventArgs extendedArgs = ExtendedEventArgs.Empty; 
    protected void OnExtendedEvent(EventArgs e) 
    { 
     // some stuff done 
     // new information the ExtendedEventArgs object needs 
     // is not available until this point 

     extendedArgs.someProperty1 = someStuff; 
     extendedArgs.someProperty2 = someOtherStuff; 

     ExtendedEvent(this, extendedArgs); 
    } 

EDIT: Sửa mã ví dụ, nên rõ ràng hơn bây giờ.

+1

Nguồn gốc không phải là vấn đề, lớp dẫn xuất chỉ có thể gọi base.OnExtendedEvent với EventArgs.Empty. Nói chung, đừng sợ tạo ra rác thải ngắn. –

+0

Tôi nghĩ bạn có nghĩa là bất biến thay vì có thể thay đổi. Bất biến có nghĩa là bạn không thể thay đổi nó. – aaronb

Trả lời

3

Tôi sẽ tạo một đối tượng bất biến mới mỗi khi nó được kích hoạt, vì có các giá trị trong đối số sự kiện.

Lý do chính là điều gì sẽ xảy ra nếu sự kiện mới được kích hoạt lại trong khi sự kiện hiện có đang được xử lý?

Điều này có thể sẽ xảy ra trong các ứng dụng đa luồng nhưng thậm chí có thể xảy ra trên một sợi đơn được thể hiện bằng các ví dụ sau:

sự kiện đầu tiên được bắn với các giá trị sau:

extendedArgs.someProperty1 = "Fire 1"; 
extendedArgs.someProperty2 = "Fire 1 Other Stuff"; 

Sau đó, bằng cách nào đó trình xử lý sự kiện đầu tiên thực hiện điều gì đó khiến sự kiện được kích hoạt lại với các đối số sau:

extendedArgs.someProperty1 = "Fire 2"; 
extendedArgs.someProperty2 = "Fire 2 Other Stuff"; 

Tất cả các trình xử lý sự kiện e cho sự kiện thứ hai được xử lý, và bây giờ chúng tôi đang trở lại để xử lý phần còn lại của xử lý sự kiện cho sự kiện đầu tiên.

Bây giờ vì cùng một đối tượng được sử dụng, tất cả các trình xử lý sự kiện cho sự kiện đầu tiên sẽ có "Fire 2" làm someProperty1 của chúng, vì sự kiện thứ hai ghi đè các giá trị.

Vì @nobugz đã đề cập không ngại tạo rác thải ngắn.

1

Tôi hơi bối rối bởi mã OnExtendedEvent của bạn - bạn có ý định redispatch sự kiện dưới dạng SomeEvent không?

Khi một khách hàng cho biết thêm một event handler, họ hy vọng họ có thể loại bỏ các xử lý sự kiện trong khi xử lý sự kiện này, như thế này:

someObject.SomeEvent += OnSomeEvent; 
// ... 
private void OnSomeEvent(object sender, EventArgs e) 
{ 
    someObject.SomeEvent -= OnSomeEvent; 
} 

Nếu bạn không làm theo các thực hành điều phối tiêu chuẩn, mã này sẽ ném một ngoại lệ rất nhiều đến sự ngạc nhiên của người sử dụng mã của bạn.

+0

Xin chào, xin lỗi mã IS khó hiểu. Đã sửa lỗi: D – Dan7

5

Trước hết, tại sao lại đưa đối số EventArgs vào phương thức kích hoạt nếu bạn chỉ bỏ qua nó? Đó là chất thải thực sự, nhưng tiêu thụ tài nguyên ít vấn đề hơn lời nói dối mà phương pháp của bạn đang nói với người gọi của nó. Chỉ cần vượt qua đối số trên thông qua, phương pháp bắn của bạn có thể sẽ không có thông tin liên quan tiếp cận để tạo ra các EventArgs đối tượng anyway:

protected virtual OnSomeEvent(EventArgs e) 
{ 
    var handler = SomeEvent; 
    if (handler != null) 
    { 
     handler(this, e); 
    } 
} 

Vì vậy, bây giờ mà chúng tôi có mà thẳng, nếu EventArgs của bạn đối tượng không có thông tin có ý nghĩa để nói thuê bao của bạn, chỉ cần sử dụng EventArgs.Empty, đó là những gì nó có cho. Bạn có thể làm theo cùng một mẫu cho các lớp EventArgs tùy chỉnh của bạn, nhưng thành thật mà nói, bạn đang lo lắng về không có gì. Tạo các đối tượng EventArgs sẽ không bao giờ là một nút cổ chai trong ứng dụng của bạn, và nếu có, bạn có vấn đề về thiết kế.

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