2009-07-14 40 views
18

Sự kiện ảo hoạt động như thế nào? Bạn sẽ ghi đè nó như thế nào? Làm thế nào mà sẽ làm việc? Và trong trường hợp nào bạn sẽ làm điều đó?C#: Sự kiện ảo là gì và chúng có thể được sử dụng như thế nào?

Ví dụ: có phải là sự thay thế ok cho các phương pháp OnEvent được bảo vệ không? Vì vậy, các lớp kế thừa có thể chỉ ghi đè lên sự kiện và nâng cao nó trực tiếp? Hoặc điều đó sẽ sai hoặc không hoạt động?

MSDN nói này về nó:

Một sự kiện có thể được đánh dấu là một sự kiện ảo bằng cách sử dụng các từ khóa ảo. Điều này cho phép các lớp dẫn xuất ghi đè hành vi sự kiện bằng cách sử dụng từ khóa ghi đè. Một sự kiện ghi đè một sự kiện ảo cũng có thể được niêm phong, trong đó xác định rằng đối với các lớp dẫn xuất, nó không còn là ảo nữa.

Nhưng điều đó không làm tôi khôn ngoan hơn nhiều. Các công cụ niêm phong là hiển nhiên mặc dù.

Lưu ý: Tôi đã xem câu hỏi How virtual events work in C# ?, nhưng thực tế không phải là sự kiện ảo hoạt động như thế nào. Thay vào đó là cách mà người đó nhận được kết quả mà anh ta nhận được từ việc sử dụng chúng. Cố gắng tìm ra sự kiện ảo nào từ ví dụ của anh ấy và câu trả lời, nhưng thực sự không thể hiểu được điều đó.

+0

Bài viết "Sự kiện ảo trong C#: Đã xảy ra sự cố" - http://www.viva64.com/en/b/0453/ –

Trả lời

23

Sự kiện ảo chỉ đơn giản là sự kiện có thể được ghi đè trong lớp dẫn xuất.

Bạn có hài lòng với khái niệm về thuộc tính ảo, với trình khởi động và thiết lập có thể bị ghi đè không? Nếu vậy, bạn có thể nghĩ về một sự kiện ảo theo cách giống hệt nhau: thay vì getter và setter, có một thao tác "thêm" và thao tác "xóa". Đây có thể là ảo, do đó xử lý đa hình. Bạn thực hiện chúng giống như cách bạn triển khai bất kỳ thành viên ảo/ghi đè nào khác.

Ví dụ:

using System; 

class Base 
{ 
    public virtual event EventHandler Foo 
    { 
     add 
     { 
      Console.WriteLine("Base Foo.add called"); 
     } 
     remove 
     { 
      Console.WriteLine("Base Foo.remove called"); 
     } 
    } 
} 

class Derived : Base 
{ 
    public override event EventHandler Foo 
    { 
     add 
     { 
      Console.WriteLine("Derived Foo.add called"); 
     } 
     remove 
     { 
      Console.WriteLine("Derived Foo.remove called"); 
     } 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     Base x = new Derived(); 

     x.Foo += (sender, args) => {}; 
    } 
} 

Lưu ý rằng các sự kiện chính nó là không chịu trách nhiệm cho những gì sẽ xảy ra khi nó được nâng lên - chỉ cần thêm/gỡ bỏ phụ. (Trong C#, anyway; bản thân CLR có khái niệm nâng cao, nhưng chúng tôi sẽ bỏ qua điều đó cho thời điểm này.)

Bạn cũng có thể muốn đọc my article on events nếu bạn hơi mơ hồ về sự khác biệt giữa sự kiện và một đại biểu.

Cá nhân tôi thấy nó rất hiếm khi tôi muốn có sự kiện ảo.

+0

Nếu lớp cha nâng cao sự kiện bị ghi đè, nó sẽ vẫn là sự kiện tương tự, đúng ? Vì vậy, nếu bạn có 'class A' và' class A: B', các thuê bao sẽ đăng ký cùng một sự kiện của một đối tượng cho dù nó được thực hiện như A hay B? – Svish

+1

Không tăng là hoàn toàn riêng biệt. Nếu lớp A ghi đè lên việc thêm/xóa và không gọi lên thêm/xóa lớp B, thì cơ chế lớp B để nâng cao sự kiện được gọi, thì không có trình xử lý nào được gọi.Hãy suy nghĩ về nó tất cả về phương pháp đồng bằng - sự kiện cung cấp thêm/loại bỏ mà có thể được ảo, nhưng không chỉ định bất cứ điều gì về ngữ nghĩa của việc nâng cao sự kiện. –

+0

Vì vậy, để nó hoạt động đúng, bạn sẽ phải làm base.add và base.remove hoặc cái gì đó? (Nếu điều đó tồn tại ...) – Svish

0

Cũng lưu ý rằng trong C# một lớp dẫn xuất không thể kích hoạt sự kiện hoàn toàn được xác định trong lớp cơ sở (không có vấn đề gì nó có sửa đổi). Vì vậy, chúng ta cần có một sự kiện mới hoặc ghi đè cho lớp dẫn xuất và trong hầu hết các trường hợp, một sự kiện quan trọng được ưu tiên hơn nếu cùng một sự kiện có nghĩa là được kích hoạt.

+0

Nhưng điều đó có thể dễ dàng được giải quyết bằng cách tạo phương thức 'Raise ...' được bảo vệ trong lớp cơ sở và gọi nó từ lớp dẫn xuất. – MarioDS

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