2009-01-20 28 views

Trả lời

16

C++/CLI cho phép bạn ghi đè raise trong trình xử lý custom event để bạn không phải kiểm tra null hoặc sao chép khi tăng sự kiện. Tất nhiên, bên trong raise tùy chỉnh của bạn, bạn vẫn phải thực hiện việc này.

Ví dụ, chuyển thể từ MSDN cho đúng đắn:

public delegate void f(int); 

public ref struct E { 
    f^_E; 
public: 
    void handler(int i) { 
     System::Console::WriteLine(i); 
    } 

    E() { 
     _E = nullptr; 
    } 

    event f^ Event { 
     void add(f^d) { 
     _E += d; 
     } 
     void remove(f^d) { 
     _E -= d; 
     } 
     void raise(int i) { 
     f^ tmp = _E; 
     if (tmp) { 
      tmp->Invoke(i); 
     } 
     } 
    } 

    static void Go() { 
     E^ pE = gcnew E; 
     pE->Event += gcnew f(pE, &E::handler); 
     pE->Event(17); 
    } 
}; 

int main() { 
    E::Go(); 
} 
28

Đây không phải là toàn bộ câu chuyện! Bạn thường không phải lo lắng về các trình xử lý sự kiện null trong C++/CLI. Mã cho các kiểm tra này được tạo cho bạn. Hãy xem xét lớp C++/CLI tầm thường sau đây.

public ref class MyClass 
{ 
public: 
    event System::EventHandler^MyEvent; 
}; 

Nếu bạn biên dịch lớp này, và tháo rời nó bằng cách sử Reflector, bạn lấy mã C# sau.

public class MyClass 
{ 
    // Fields 
    private EventHandler <backing_store>MyEvent; 

    // Events 
    public event EventHandler MyEvent 
    { 
     [MethodImpl(MethodImplOptions.Synchronized)] add 
     { 
      this.<backing_store>MyEvent = (EventHandler) Delegate.Combine(this.<backing_store>MyEvent, value); 
     } 
     [MethodImpl(MethodImplOptions.Synchronized)] remove 
     { 
      this.<backing_store>MyEvent = (EventHandler) Delegate.Remove(this.<backing_store>MyEvent, value); 
     } 
     raise 
     { 
      EventHandler <tmp> = null; 
      <tmp> = this.<backing_store>MyEvent; 
      if (<tmp> != null) 
      { 
       <tmp>(value0, value1); 
      } 
     } 
    } 
} 

Kiểm tra thông thường đang được thực hiện trong phương pháp nâng cao. Trừ khi bạn thực sự muốn hành vi tùy chỉnh, bạn sẽ cảm thấy thoải mái tuyên bố sự kiện của bạn như trong lớp trên, và nâng cao nó mà không sợ một trình xử lý null.

+0

Vấn đề của tôi với phương pháp này là phương pháp "nâng cao" không phải là riêng tư (như trong C#) và hiển thị trong phần intellisense. –

+1

@Filip: Vì vậy, đi với một sự kiện tùy chỉnh và đặt 'riêng:' ở phía trước. –

7

Nếu vấn đề của bạn là tăng là không tin, sau đó thực hiện nó một cách rõ ràng như các tài liệu nói:

http://msdn.microsoft.com/en-us/library/5f3csfsa.aspx

Nói tóm lại:

Nếu bạn chỉ cần sử dụng sự kiện từ khóa, bạn tạo sự kiện "tầm thường". Trình biên dịch tạo ra thêm/loại bỏ/tăng và thành viên đại biểu cho bạn. Hàm nâng cao (như tài liệu nói) kiểm tra nullptr. sự kiện tầm thường được ghi nhận ở đây:

http://msdn.microsoft.com/en-us/library/4b612y2s.aspx

Nếu bạn muốn "kiểm soát nhiều", ví dụ để làm tăng tư nhân, sau đó bạn phải thực hiện một cách rõ ràng các thành viên như trong liên kết. Bạn phải khai báo rõ ràng một thành viên dữ liệu cho loại ủy nhiệm. Sau đó, bạn sử dụng kiện từ khóa để khai báo các thành viên sự kiện liên quan, như trong ví dụ Microsoft:

// event keyword introduces the scope wherein I'm defining the required methods 
// "f" is my delegate type 
// "Event" is the unrealistic name of the event itself 
event f^ Event 
{ 
     // add is public (because the event block is public) 
     // "_E" is the private delegate data member of type "f" 
     void add(f^d) { _E += d; } 

    // making remove private 
    private: 
     void remove(f^d) { _E -= d; } 

    // making raise protected 
    protected: 
     void raise(int i) 
     { 
     // check for nullptr 
     if (_E) 
     { 
      _E->Invoke(i); 
     } 
     } 
}// end event block 

dài dòng, nhưng có nó được.

-reilly.

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