เพื่อทำความเข้าใจความแตกต่างคุณสามารถดู 2 ตัวอย่างนี้
ตัวอย่างกับ Delegates (การดำเนินการในกรณีนี้คือผู้รับมอบสิทธิ์ประเภทหนึ่งที่ไม่ส่งคืนค่า)
public class Animal
{
public Action Run {get; set;}
public void RaiseEvent()
{
if (Run != null)
{
Run();
}
}
}
ในการใช้ผู้รับมอบสิทธิ์คุณควรทำสิ่งนี้
Animale animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();
รหัสนี้ใช้งานได้ดี แต่คุณอาจมีจุดอ่อนบางประการ
ตัวอย่างเช่นถ้าฉันเขียนสิ่งนี้
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;
ด้วยบรรทัดสุดท้ายของรหัสฉันได้ลบล้างพฤติกรรมก่อนหน้านี้เพียงหนึ่งรายการที่ขาดหายไป+
(ฉันใช้+
แทน+=
)
อีกจุดที่อ่อนแอคือระดับที่ใช้ของคุณทุกAnimal
ระดับสามารถเพิ่มเพียงแค่เรียกมันว่าRaiseEvent
animal.RaiseEvent()
เพื่อหลีกเลี่ยงจุดอ่อนนี้คุณสามารถใช้events
ใน c #
คลาส Animal ของคุณจะเปลี่ยนไปในลักษณะนี้
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"));
}
}
เพื่อโทรหาเหตุการณ์
Animale animal= new Animal();
animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
animal.RaiseEvent();
ความแตกต่าง:
- คุณไม่ได้ใช้ทรัพย์สินสาธารณะ แต่เป็นฟิลด์สาธารณะ (โดยมีเหตุการณ์ที่คอมไพเลอร์ปกป้องฟิลด์ของคุณจากการเข้าถึงที่ไม่ต้องการ)
- ไม่สามารถกำหนดกิจกรรมได้โดยตรง ในกรณีนี้คุณไม่สามารถทำข้อผิดพลาดก่อนหน้านี้ที่ฉันได้แสดงให้เห็นด้วยการลบล้างพฤติกรรม
- ไม่มีใครนอกชั้นเรียนของคุณสามารถยกเหตุการณ์ได้
- เหตุการณ์สามารถรวมอยู่ในการประกาศอินเทอร์เฟซในขณะที่ฟิลด์ไม่สามารถรวมได้
หมายเหตุ
EventHandler ประกาศเป็นผู้รับมอบสิทธิ์ต่อไปนี้:
public delegate void EventHandler (object sender, EventArgs e)
ต้องใช้ผู้ส่ง (ประเภทวัตถุ) และอาร์กิวเมนต์เหตุการณ์ ผู้ส่งเป็นโมฆะหากมาจากวิธีการคงที่
คุณสามารถใช้EventHAndler
แทนตัวอย่างนี้ที่ใช้EventHandler<ArgsSpecial>
อ้างอิงที่นี่สำหรับเอกสารเกี่ยวกับ EventHandler