Người gửi của một sự kiện phải luôn là một Đối tượng chung?


10

Khi lập trình các sự kiện trong C #, bạn nên tạo một đại biểu dưới dạng:

delegate XEventHandler(object sender, XEventArgs e);

Câu hỏi của tôi là về lập luận đầu tiên của đại biểu object sender,. Nó luôn luôn phải là một chung chung object? Có một người gửi loại objectluôn dẫn đến mã tương tự như thế này.

val = ((ConcreteType)sender).Property;

hoặc, thậm chí dài dòng hơn,

ConcreteType obj = sender as ConcreteType
if (obj != null) { ... }

Một lập luận chống lại người gửi được gõ mạnh là các đối tượng khác có thể chuyển tiếp sự kiện mà không phải lo lắng về loại. Mặc dù điều này có thể có ý nghĩa trong môi trường GUI, tôi không chắc liệu nó có thể có lợi ngoài GUI hay không.

Điều gì xảy ra nếu lớp của người gửi luôn được biết đến (ít nhất là một lớp trừu tượng)? Ví dụ, nếu tôi đang thực hiện một ListChangedsự kiện trong một bản tóm tắt Listlớp, và nếu các lớp khác sẽ thừa kế nó (ví dụ LinkedList, ArrayList), nó là tất cả quyền xác định đại biểu của tôi với người gửi là loại List?

delegate ListChangedEventHander(List sender, ListChangedEventArgs e);

Hoặc, sẽ có một nhược điểm của việc thay đổi thông thường object sendersang một loại cụ thể hơn?

Câu trả lời:


10

Tại thời điểm này, nó chủ yếu là một quy ước (khá mạnh). Đó là, sẽ thật kỳ lạ nếu bạn viết một thư viện không tuân theo quy ước đó.

Các Hướng dẫn thiết kế tổ chức sự kiện nói:

NÊN sử dụng objectlàm kiểu tham số đầu tiên của trình xử lý sự kiện và gọi nó sender.

Tuy nhiên, bạn có thể lưu ý rằng hướng dẫn hiện tại nói rằng bạn không nên xác định đại biểu tùy chỉnh của riêng mình cho các sự kiện, mà hãy sử dụng EventHandler<T>thay thế, nếu bạn có thể.

Đối với thiết kế, tôi đoán rằng nó cũng thúc đẩy việc tái sử dụng các trình xử lý sự kiện, ngay cả trong bối cảnh ban đầu không được dự đoán bởi nhà thiết kế ban đầu của sự kiện.


2
Ughhh ... chỉ vì Microsoft quyết định làm cho hướng dẫn của họ đủ chung để áp dụng cho mọi người, không có nghĩa là mọi người nên làm theo hướng dẫn của họ. Các tỷ lệ rất có khả năng là "mọi người khác" không viết mã được sử dụng bởi hàng triệu nhà phát triển khác. Tôi đã giới thiệu khoảng 2/3 trong số các khuyến nghị từ liên kết bạn cung cấp.
Dunk

Nói thật với bạn, "hướng dẫn" này ít nhiều có cảm giác giống như ký hiệu Hungary của Windows API. Một người xuất sắc đã bắt đầu nó vì một lý do thực sự tốt và sau đó mọi người khác bắt đầu lạm dụng nó. Khi có một hướng dẫn, tốt hơn là có một lý do chính đáng đằng sau hướng dẫn đó. Và điều tôi nghĩ rằng lý do cho hướng dẫn này là System.Windows.Formskhông gian tên là nơi các sự kiện được sử dụng nhiều nhất và nó có ý nghĩa để đăng ký vào Clicksự kiện của Buttonhoặc a CheckBox. Do đó, người gửi cần phải chung chung. ...
sampathsris

... Nhưng khi nói đến các lĩnh vực chức năng khác, cụ thể hơn, có chứa, người gửi có thể không cần phải là một lớp chung. Xem lại ví dụ của tôi về hệ thống phân cấp lớp của Lists.
sampathsris

11
@ Dunk: Và đó là điểm chính. Hướng dẫn này xuất phát từ Nguyên tắc thiết kế khung, chủ yếu liên quan đến mã được người khác sử dụng . Không phải vì đó là giải pháp tốt nhất, mà vì nó ít gây ngạc nhiên nhất. Đó là lựa chọn tốt nhất cho một khung . Đối với các thư viện nhỏ hơn, nếu trường hợp sử dụng được chỉ định rõ, sẽ ít áp dụng hướng dẫn hơn. Microsoft nói rõ ràng như vậy ở đầu cuốn sách.
Magus

1
Tôi không tranh cãi với câu trả lời, tôi thậm chí còn ủng hộ nó vì nó đến từ một nguồn có uy tín. Tôi chỉ nói rằng tôi sẽ không sử dụng các hướng dẫn. Nếu một sự kiện được cho là gửi dữ liệu cụ thể thì tôi sẽ chỉ gửi dữ liệu cụ thể. Ngoài ra, tính năng sự kiện chỉ hoạt động tốt nếu bạn sử dụng chúng theo cách chúng được sử dụng.
Dunk

0

Lý do cho khuyến nghị là nó cho phép các thay đổi trong tương lai không nhất thiết yêu cầu thay đổi mã hiện có và đặc biệt là giao diện công cộng.

Bản thân cơ chế sự kiện vẫn có thể được sử dụng cho các sự kiện kiểu "VB6", nhưng bạn sẽ phải thay đổi tất cả người tiêu dùng hiện tại nếu bạn cần thay đổi chữ ký (hoặc tệ hơn: tạo phiên bản mới của cùng một sự kiện). Với cách tiếp cận được đề xuất, miễn là các mục mới hơn kế thừa từ các mục hiện có, bạn có thể cập nhật chữ ký mà không sửa mã hiện có.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.