2010-10-15 17 views
25

Xét đoạn code dưới đây:Invocation của một sự kiện lĩnh vực giống như đa hình

public class TableMain { 
    public virtual event Action UpdateFilter; 
    .... 
} 

public class TableSub : TableMain { 
    public override event Action UpdateFilter; 

    public void UpdateQuery() { 
     ..... 
     if (UpdateFilter!=null) { 
       UpdateFilter(); // Invocation of polymorphic field-like event??? 
     } 
    } 
} 

Trong mã này ReSharper cho thấy cảnh báo "gọi của sự kiện lĩnh vực giống như đa hình".

Câu hỏi của tôi là: Điều đó thực sự có ý nghĩa gì? Và nó là một cảnh báo cho một thực hành lập trình xấu? Ngoài ra, thực tiễn không tốt là gọi một sự kiện đa hình? (Biết rằng một sự kiện chỉ có thể được nâng lên từ lớp đã tuyên bố nó.)

Trả lời

41

Vâng, bạn đã thực sự nhận được hai sự kiện giống như trường ở đây. Ghi đè của bạn sẽ ghi đè phần thêm/xóa, nhưng bạn sẽ có hai trường - một trong số TableMain và một trong số TableSub. Chỉ một số trong TableSub sẽ không bao giờ là rỗng, trừ khi giá trị được đặt rõ ràng trong TableMain ... vì vậy nếu TableMain từng cố gắng tự nâng cao sự kiện, nó sẽ không gọi cùng một bộ xử lý như trong TableSub. Về cơ bản, nó sẽ hành xử kỳ lạ.

Cách tiếp cận đúng là cung cấp một phương pháp bảo vệ trong TableMain để cho phép sự kiện để được nâng lên bởi lớp con:

protected void OnUpdateFilter() 
{ 
    Action handler = UpdateFilter; 
    if (handler != null) 
    { 
     handler(); 
    } 
} 

Sau đó thực hiện sự kiện này không phải là ảo, và loại bỏ các ghi đè trong TableSub.

Lưu ý rằng chữ ký sự kiện của bạn không khớp với quy ước bình thường cho các sự kiện - bất kỳ lý do gì để không sử dụng EventHandler?

+0

Điều này nghe giống như một nguồn lỗi tiềm năng lớn đối với tôi, bởi vì nó rất có thể không phải là những gì bạn mong đợi khi viết mã như vậy. Không bao giờ có nhu cầu suy nghĩ về khía cạnh cụ thể đó trước đây. Bạn có biết tại sao các sự kiện ảo được cho phép cú pháp không? –

+1

@ John. Về --- "Lưu ý rằng chữ ký sự kiện của bạn không khớp với quy ước bình thường cho các sự kiện - bất kỳ lý do gì để không sử dụng EventHandler?" Tôi chỉ đang sử dụng các đại diện "Hành động" hiện có, vì trong trường hợp này tôi không cần bất kỳ đối số (đối tượng, eventargs) trong các thuê bao cho sự kiện này. Đó là (một lần nữa) một thực hành lập trình xấu? Bạn có nên tạo một đại biểu riêng biệt (trống) cho trường hợp này không? –

+1

@Thomas: Có nhiều cách bạn * có thể * sử dụng chúng một cách hợp lý - ví dụ, bạn có thể đăng nhập từng đăng ký và sau đó chuyển nó lên cơ sở triển khai. Ngoài ra, bạn cần có khả năng có các sự kiện trừu tượng hiệu quả để có thể đưa chúng vào các giao diện. –

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