2015-05-27 13 views
7

Tôi có đoạn mã sau vào lớp học của tôiBạn có thể sử dụng phép gán bằng khi loại bỏ các thành viên đại biểu trong một phương pháp xử lý?

public class Receiver : IReceiver 
{ 

    public event EventHandler Received; 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if (Received != null) 
      { 
       foreach (EventHandler delegateMember in Received.GetInvocationList()) 
       { 
        Received -= delegateMember; 
       } 
      } 
     } 
    } 
} 

Mã này hoạt động trong khi tôi vứt bỏ lớp học của tôi bất kỳ sự kiện được nối với trường hợp nhận, sẽ được xóa riêng lẻ.

Tôi đã tự hỏi nếu hơn là để tiết về nó, nếu phiên bản ngắn gọn sau đây sẽ có tác dụng tương tự

protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      Received = null; 
     } 
    } 

Về cơ bản này đi xuống đến bao quá tải toán tử đã được tạo ra bởi Microsoft khi triển khai quá tải ủy nhiệm. Tôi biết rằng tất cả tài liệu hướng dẫn đều sử dụng dấu + = để đăng ký và - = để hủy đăng ký khỏi sự kiện. Tôi cũng đã thấy tài liệu nói rằng sự kiện sẽ được gán cho null khi người đăng ký cuối cùng bị xóa. Những gì các tài liệu không nói là liệu gán sự kiện để null, sẽ có tác dụng hủy đăng ký tất cả các sự kiện?

Tôi rất muốn biết nếu điều này là có thể, và nếu có bất kỳ tài liệu nói rằng mã ngắn gọn nhất có thể là hành vi đúng.

Cập nhật:

Tôi đã làm một số đào hơn với C# biên dịch và đã phát hiện ra rằng sự phân công null chỉ hoạt động trong phạm vi lớp học, nơi sự kiện được định nghĩa. Các + = và - = luôn luôn có sẵn từ cả bên trong và bên ngoài lớp. Điều này khiến tôi nghĩ rằng việc sử dụng phiên bản = null có thể chấp nhận được. Tuy nhiên, đây là suy đoán, tôi vẫn chưa thấy bất kỳ tài liệu nào nêu rõ rằng đây là chức năng được hỗ trợ.

+3

@DStanley Các đại biểu sẽ vẫn được tham khảo các đối tượng, vâng, nhưng các đại biểu bản thân sẽ không còn được bắt nguồn từ, hoặc truy cập từ một gốc, vì vậy nó sẽ không được giữ các đối tượng tham chiếu còn sống. – Servy

+0

Tôi đã kiểm tra một lúc trước khi đăng câu hỏi. Câu hỏi cơ bản là sử dụng = câu sử dụng - =. Trong MSDN gần nhất mà tôi có thể tìm thấy là ở dưới cùng của trang này https://msdn.microsoft.com/en-us/library/ms366768(v=vs.90).aspx nó nói rằng null sẽ được chỉ định khi trường hợp cuối cùng của trình xử lý sự kiện bị hủy đăng ký. –

Trả lời

4

Không có lý do để không chỉ gán null để các đại biểu ở đây.

Bạn sẽ không được có thể để chỉ định null nếu bạn ở ngoài lớp đã xác định sự kiện. Đối với bất kỳ ai sử dụng lớp, họ chỉ nên quan tâm đến những người xử lý riêng của họ, rằng họ có thể thêm hoặc xóa. Họ không thể truy cập các trình xử lý của người khác.

Bạn cần phải nhớ rằng các đại biểu là không thay đổi. Sử dụng += trên một sự kiện không làm thay đổi đại biểu để thêm một phương thức mới cho đại biểu đó, nó tạo ra một đại biểu mới, khi được gọi, gọi cả hai đại biểu được cộng lại với nhau. Sử dụng -= tạo một đại biểu gọi tất cả các lời gọi của toán hạng đầu tiên ngoại trừ toán hạng thứ hai. Vì vậy, việc gọi số -= liên tục tạo ra ngày càng nhiều đại biểu mà mỗi người gọi ít hơn và ít công cụ hơn, cho đến khi cuối cùng bạn nhận được điểm mà đại biểu không gọi bất cứ điều gì nữa. Chỉ cần gán null tương đương với việc chỉ tạo đại biểu không thực hiện điều gì và chỉ định trực tiếp điều đó.

Vì vậy, khi bạn gọi -= hơn và hơn đại biểu ban đầu đã được gán cho sự kiện trước khi bạn bắt đầu vẫn còn tồn tại, cũng như N đại biểu trung gian. Điều đó nói rằng, không ai trong số các đại biểu có khả năng được tham chiếu bởi bất kỳ yếu tố bắt nguồn từ, vì vậy tất cả họ sẽ đủ điều kiện để thu thập. Nếu bạn chỉ gán null bạn vẫn có cùng một đại biểu mồ côi ban đầu ở đó, bạn chỉ không có bất kỳ đại biểu trung gian nào nữa.

+0

Tôi hiểu mọi thứ bạn đã đăng ở đây và tôi biết rằng mã sẽ biên dịch cả hai cách. Tôi cho rằng phần quan trọng của câu hỏi là ... - đó là - = làm cái gì khác nữa, nhưng bài tập = không làm? Và nếu đó là cách bạn có thể chắc chắn? Tham chiếu duy nhất đến gần với điều này mà tôi đã tìm thấy cho đến nay là ở dưới cùng của trang này https://msdn.microsoft.com/en-us/library/ms366768(v=vs.90).aspx mà rõ ràng nói để sử dụng toán tử - =. Nó nói rằng bạn có thể kiểm tra cho null để xem nếu có bất kỳ thuê bao. Nó không nói rằng bạn có thể sử dụng toán tử =. –

+0

@ColinDawson Toán tử '- =' không làm bất cứ điều gì ngoài việc tạo một đại biểu mới loại trừ toán hạng thứ hai khỏi danh sách yêu cầu và sau đó gán ủy nhiệm mới đó cho toán hạng đầu tiên. Tạo một delegate mới không làm gì (a.k.a. 'null') và gán nó trực tiếp là tương đương. Tất nhiên, trừ khi bất kỳ trình xử lý sự kiện nào tham chiếu đến đối tượng xác định sự kiện (và sẽ thu hút người nhận này), không có lý do gì để làm * hoặc *, vì toàn bộ người nhận sẽ sớm ngừng được bắt nguồn từ vị trí đầu tiên. không có lý do gì để loại bỏ nó. – Servy

+0

Tôi hiểu rằng, câu hỏi không phải là bạn có thể viết nó trong mã, nhưng có tài liệu nào hỗ trợ sử dụng = null không? Tôi rất muốn có thể chỉ đơn giản là sử dụng mã terse vì nó trông rất rõ ràng, nhưng tôi muốn chắc chắn rằng dưới mui xe tất cả mọi thứ đang làm việc như dự định - giống như cách mã tiết từ ví dụ. Những gì tôi đang tìm kiếm là trích dẫn nói rằng nó là một cấu trúc cho phép. Tôi không muốn cho rằng nó hoạt động. Những gì bạn đang nói có ý nghĩa, tôi sẽ hiểu làm thế nào bạn đến với sự hiểu biết đó. –

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