2009-04-16 23 views
124

Tôi có một lớp cơ sở có chứa các sự kiện sau đây:C#: Nâng cao một sự kiện di truyền

public event EventHandler Loading; 
public event EventHandler Finished; 

Trong một lớp kế thừa từ lớp cơ sở này, tôi cố gắng để nâng cao sự kiện:

this.Loading(this, new EventHandler()); // All we care about is which object is loading. 

Tôi nhận được lỗi sau:

Sự kiện 'BaseClass.Loading' chỉ có thể xuất hiện ở phía bên tay trái của + = hoặc - = (BaseClass ')

Tôi giả định rằng tôi không thể truy cập các sự kiện này giống như các thành viên khác được kế thừa?

Trả lời

138

gì bạn phải làm, là thế này:

Trong lớp cơ sở của bạn (nơi bạn đã tuyên bố các sự kiện), tạo các phương pháp được bảo vệ có thể được sử dụng để tăng sự kiện:

public class MyClass 
{ 
    public event EventHandler Loading; 
    public event EventHandler Finished; 

    protected virtual void OnLoading(EventArgs e) 
    { 
     EventHandler handler = Loading; 
     if(handler != null) 
     { 
      handler(this, e); 
     } 
    } 

    protected virtual void OnFinished(EventArgs e) 
    { 
     EventHandler handler = Finished; 
     if(handler != null) 
     { 
      handler(this, e); 
     } 
    } 
} 

(Lưu ý rằng bạn có thể nên thay đổi những sự kiện đó ods, để kiểm tra xem bạn có phải gọi eventhandler hay không).

Sau đó, trong lớp kế thừa từ lớp cơ sở này, bạn có thể chỉ cần gọi các phương pháp OnFinished hoặc OnLoading để nâng cao sự kiện:

public AnotherClass : MyClass 
{ 
    public void DoSomeStuff() 
    { 
     ... 
     OnLoading(EventArgs.Empty); 
     ... 
     OnFinished(EventArgs.Empty); 
    } 
} 
+5

Những phương pháp này cần được bảo vệ ảo trừ khi có một lý do nào làm khác đi. –

+6

Tại sao nó phải là ảo? Tôi sẽ tuyên bố nó là ảo nếu tôi muốn thừa kế thay đổi cách thức sự kiện nên được nâng lên, nhưng hầu hết thời gian, tôi thấy không có lý do để làm điều này ... –

+0

Theo hướng dẫn Microsoft nói nó phải là ảo để người thừa kế có thể kiểm soát sự kiện .. thêm vào phương pháp được bảo vệ trên nên lấy sự kiện args, không tự tạo chúng. Câu trả lời này sai so với câu trả lời chính xác của Adam Robinson. – meandmycode

7

I am assuming I cannot access these events the same as other inherited members?

Chính xác. Thông thường cần cung cấp chức năng được bảo vệ OnXyz hoặc RaiseXyz cho mỗi sự kiện trong lớp cơ sở để cho phép tăng từ các lớp được thừa hưởng. Ví dụ:

public event EventHandler Loading; 

protected virtual void OnLoading() { 
    EventHandler handler = Loading; 
    if (handler != null) 
     handler(this, EventArgs.Empty); 
} 

gọi trong lớp kế thừa:

OnLoading(); 
111

Bạn chỉ có thể truy cập vào một sự kiện trong lớp tuyên bố, như .NET tạo các biến cá thể riêng đằng sau hậu trường thực sự giữ đại biểu. Làm việc này ..

public event EventHandler MyPropertyChanged; 

thực sự đang thực hiện việc này;

private EventHandler myPropertyChangedDelegate; 

public event EventHandler MyPropertyChanged 
{ 
    add { myPropertyChangedDelegate += value; } 
    remove { myPropertyChangedDelegate -= value; } 
} 

và làm điều này ...

MyPropertyChanged(this, EventArgs.Empty); 

là thực sự này ...

myPropertyChangedDelegate(this, EventArgs.Empty); 

Vì vậy, bạn có thể (rõ ràng) chỉ truy cập các biến thể hiện ủy nhiệm cá nhân từ bên trong tuyên bố lớp học.

Quy ước là cung cấp một cái gì đó như thế này trong lớp tuyên bố ..

protected virtual void OnMyPropertyChanged(EventArgs e) 
{ 
    EventHandler invoker = MyPropertyChanged; 

    if(invoker != null) invoker(this, e); 
} 

Sau đó bạn có thể gọi OnMyPropertyChanged(EventArgs.Empty) từ bất cứ đâu trong lớp đó hay dưới hệ thống cấp bậc thừa kế để gọi sự kiện này.

+0

Tôi đã có một số vấn đề thực hiện điều này ... http://stackoverflow.com/q/10593632/328397 – LamonteCristo

-1

Bạn có thể thử cách này, Nó làm việc cho tôi:

public delegate void MyEventHaldler(object sender, EventArgs e); 

public class B 
{ 
    public virtual event MyEventHaldler MyEvent; 
    protected override void OnChanged(EventArgs e) 
    { 
     if (MyEvent != null) 
      MyEvent(this, e); 
    } 
} 

public class D : B 
{ 
    public override event MyEventHaldler MyEvent; 
    protected override void OnChanged(EventArgs e) 
    { 
     if (MyEvent != null) 
      MyEvent(this, e); 
    } 
} 
+2

Lưu ý rằng bài viết này cảnh báo chống lại tuyên bố các sự kiện ảo và ghi đè chúng vì nó tuyên bố trình biên dịch không xử lý chính xác: https://msdn.microsoft.com/en-us/library/hy3sefw3.aspx –

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