để hiểu sự khác biệt, bạn có thể xem 2 ví dụ này
Thực hiện với các đại biểu (Hành động trong trường hợp này là một loại ủy quyền không trả về giá trị)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
để sử dụng đại biểu, bạn nên làm điều gì đó như thế này
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
mã này hoạt động tốt nhưng bạn có thể có một số điểm yếu.
Ví dụ nếu tôi viết cái này
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
với dòng mã cuối cùng, tôi đã ghi đè các hành vi trước đó chỉ với một dòng bị thiếu +
(tôi đã sử dụng +
thay vì +=
)
Một điểm yếu khác là mọi lớp sử dụng Animal
lớp của bạn có thể nâng lên RaiseEvent
chỉ cần gọi nó animal.RaiseEvent()
.
Để tránh điểm yếu này, bạn có thể sử dụng events
trong c #.
Lớp Động vật của bạn sẽ thay đổi theo cách này
public class ArgsSpecial :EventArgs
{
public ArgsSpecial (string val)
{
Operation=val;
}
public string Operation {get; set;}
}
public class Animal
{
public event EventHandler<ArgsSpecial> Run = delegate{} //empty delegate. In this way you are sure that value is always != null because no one outside of the class can change it
public void RaiseEvent()
{
Run(this, new ArgsSpecial("Run faster"));
}
}
để gọi sự kiện
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
Sự khác biệt:
- Bạn không sử dụng thuộc tính công cộng mà là trường công cộng (với các sự kiện trình biên dịch bảo vệ các trường của bạn khỏi quyền truy cập không mong muốn)
- Không thể chỉ định trực tiếp sự kiện. Trong trường hợp này, bạn không thể thực hiện lỗi trước đó mà tôi đã chỉ ra khi ghi đè hành vi.
- Không ai bên ngoài lớp học của bạn có thể nâng cao sự kiện.
- Các sự kiện có thể được đưa vào khai báo giao diện, trong khi một trường không thể
ghi chú
EventHandler được khai báo là đại biểu sau:
public delegate void EventHandler (object sender, EventArgs e)
nó nhận một người gửi (kiểu Đối tượng) và các đối số sự kiện. Người gửi là null nếu nó đến từ các phương thức tĩnh.
EventHAndler
Thay vào đó, bạn cũng có thể sử dụng ví dụ này sử dụngEventHandler<ArgsSpecial>
tham khảo ở đây cho tài liệu về EventHandler