2010-05-27 25 views
9

Gần đây tôi đã xem xét quản lý bộ nhớ và đã xem xét cách các sự kiện được quản lý, bây giờ, tôi thấy cú pháp thêm/xóa rõ ràng cho đăng ký sự kiện.Sự kiện rõ ràng thêm/xóa, hiểu lầm?

Tôi nghĩ điều đó khá đơn giản, việc thêm/xóa chỉ cho phép tôi thực hiện logic khác khi tôi đăng ký và hủy đăng ký? Tôi có nhận được nó hay không?

Ngoài ra, khi tôi ở đây, bất kỳ lời khuyên/phương pháp hay nhất nào để làm sạch bộ xử lý sự kiện của tôi.

Trả lời

3

Thêm/xóa cú pháp thường được sử dụng để "chuyển tiếp" triển khai sự kiện cho một lớp khác.

Dọn dẹp đăng ký (không phải "xử lý sự kiện") được thực hiện tốt nhất bằng cách triển khai IDisposable.

CẬP NHẬT: Có một số biến thể đối tượng nào cần triển khai IDisposable. Nhóm Rx đưa ra quyết định tốt nhất từ ​​quan điểm thiết kế: đăng ký là IDisposable. Các sự kiện .NET thông thường không có đối tượng đại diện cho thuê bao, do đó sự lựa chọn giữa nhà xuất bản (lớp mà sự kiện được xác định) và người đăng ký (thường là lớp chứa hàm thành viên được đăng ký). Mặc dù bản năng thiết kế của tôi thích làm cho người đăng ký IDisposable, hầu hết mã thực tế đều làm cho nhà xuất bản IDisposable: đó là việc triển khai dễ dàng hơn và có thể có trường hợp không có phiên bản người đăng ký thực.

(Tức là, nếu mã thực sự dọn dẹp đăng ký sự kiện nào cả. Hầu hết các mã không.)

+0

Ha, tôi gọi chúng là đăng ký khi nói chuyện với đồng nghiệp của tôi nhưng thời điểm tôi đăng câu hỏi, tôi đang sử dụng thuật ngữ sai. Cảm ơn bạn đã làm rõ. – Hammerstein

6

Vâng, thêm/gỡ bỏ cú pháp cho phép bạn thực hiện logic thuê bao của riêng bạn. Khi bạn bỏ chúng ra (ký pháp chuẩn cho một sự kiện) trình biên dịch tạo ra các triển khai tiêu chuẩn. Điều đó cũng giống như các thuộc tính tự động.

Trong ví dụ sau, không có sự khác biệt thực sự giữa Event1 và Event2.

public class Foo 
{ 
    private EventHandler handler; 
    public event EventHandler Event1 
    { 
    add { handler += value; } 
    remove { handler -= value; } 
    } 

    public event EventHandler Event2; 
} 

Nhưng đây là chủ đề riêng biệt từ trình xử lý 'dọn dẹp'. Đây là lớp đăng ký nên thực hiện việc hủy đăng ký. Các lớp xuất bản không thể giúp đỡ với điều này rất nhiều.
Hãy tưởng tượng một lớp học sẽ 'dọn sạch' danh sách đăng ký các sự kiện của nó. Nó chỉ có thể làm điều này một cách hợp lý khi nó được xử lý chính nó, và sau đó nó không có khả năng làm việc như một lớp Disposed thường trở thành sưu tập ngay sau khi nó được xử lý.

+1

Tôi tin rằng người dùng cuối không thể làm: 'Foo foo = ...; foo.Event1 (người gửi, e); 'nhưng có thể làm' foo.Event2 (null, null); '. – user7116

+0

Cảm ơn bạn đã làm ví dụ và làm rõ. Tôi nghĩ rằng tôi đã có nó, nhưng tôi đã suy nghĩ về nó! Tôi sẽ đăng câu hỏi về quản lý bộ nhớ trong một câu hỏi riêng, vì tôi nghĩ có nhiều hơn tôi muốn hỏi. – Hammerstein

+0

Tôi nhầm, bạn nhận được lỗi trong cả hai trường hợp, nhưng bạn nhận được lỗi trong trường hợp thứ hai, 'lỗi CS0070: Sự kiện 'Program.Foo.Event2' chỉ có thể xuất hiện ở phía bên tay trái của + = hoặc - = (trừ khi được sử dụng từ bên trong loại 'Program.Foo') '. – user7116

9

Thuộc tính thêm/xóa về cơ bản có cùng logic khi sử dụng thuộc tính set/get với các thành viên khác. Nó cho phép bạn tạo thêm một số logic trong khi đăng ký một sự kiện và đóng gói chính sự kiện đó.

Một ví dụ điển hình cho TẠI SAO bạn muốn thực hiện, là ngừng tính toán thêm khi không cần thiết (không ai đang nghe sự kiện).

Ví dụ, cho phép nói những sự kiện được kích hoạt bởi một bộ đếm thời gian, và chúng tôi không muốn bộ đếm thời gian để làm việc nếu không ai được đăng ký cho sự kiện này:

private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer(); 
private EventHandler _explicitEvent; 
public event EventHandler ExplicitEvent 
{ 
    add 
    { 
     if (_explicitEvent == null) timer.Start(); 
     _explicitEvent += value; 
    } 
    remove 
    { 
     _explicitEvent -= value; 
     if (_explicitEvent == null) timer.Stop(); 
    } 
} 

Bạn có thể muốn khóa thêm/gỡ bỏ với một đối tượng (một suy nghĩ) ...

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