Apa perbedaan antara delegasi dan acara?

Jawaban:

283

Sebuah acara deklarasi menambahkan lapisan abstraksi dan perlindungan pada delegasi misalnya. Perlindungan ini mencegah klien dari delegasi mengatur ulang delegasi dan daftar doa dan hanya memungkinkan menambah atau menghapus target dari daftar doa.

mmcdole
sumber
44
Jika tentu saja, lapisan perlindungan ini juga mencegah "klien" (kode di luar kelas / struct yang mendefinisikan) dari memanggil delegasi, dan dari cara apa pun mendapatkan objek delegasi "di belakang" acara.
Jeppe Stig Nielsen
7
Tidak sepenuhnya benar. Anda dapat mendeklarasikan suatu peristiwa tanpa instance delegasi backend. Di c #, Anda dapat mengimplementasikan suatu peristiwa secara eksplisit dan menggunakan struktur data backend yang berbeda dari pilihan Anda.
Miguel Gamboa
3
@mmcdole dapatkah Anda memberikan contoh untuk menjelaskan tentangnya?
vivek nuna
103

Untuk memahami perbedaan Anda dapat melihat 2 contoh ini

Contoh dengan Delegasi (dalam hal ini, Aksi - itu adalah semacam delegasi yang tidak mengembalikan nilai)

public class Animal
{
    public Action Run {get; set;}

    public void RaiseEvent()
    {
        if (Run != null)
        {
            Run();
        }
    }
}

Untuk menggunakan delegasi, Anda harus melakukan sesuatu seperti ini:

Animal animal= new Animal();
animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running") ;
animal.RaiseEvent();

Kode ini berfungsi dengan baik tetapi Anda dapat memiliki beberapa titik lemah.

Misalnya, jika saya menulis ini:

animal.Run += () => Console.WriteLine("I'm running");
animal.Run += () => Console.WriteLine("I'm still running");
animal.Run = () => Console.WriteLine("I'm sleeping") ;

dengan baris kode terakhir, saya telah menimpa perilaku sebelumnya hanya dengan satu yang hilang +(saya telah menggunakan =alih-alih +=)

Kelemahan lain adalah bahwa setiap kelas yang menggunakan Animalkelas Anda dapat meningkatkan RaiseEventhanya dengan menyebutnya animal.RaiseEvent().

Untuk menghindari titik-titik lemah ini Anda dapat menggunakan eventsc #.

Kelas Hewan Anda akan berubah dengan cara ini:

public class ArgsSpecial : EventArgs
{
    public ArgsSpecial (string val)
    {
        Operation=val;
    }

    public string Operation {get; set;}
} 

public class Animal
{
    // Empty delegate. In this way you are sure that value is always != null 
    // because no one outside of the class can change it.
    public event EventHandler<ArgsSpecial> Run = delegate{} 

    public void RaiseEvent()
    {  
         Run(this, new ArgsSpecial("Run faster"));
    }
}

untuk memanggil acara

 Animal animal= new Animal();
 animal.Run += (sender, e) => Console.WriteLine("I'm running. My value is {0}", e.Operation);
 animal.RaiseEvent();

Perbedaan:

  1. Anda tidak menggunakan properti publik tetapi bidang publik (menggunakan acara, kompiler melindungi bidang Anda dari akses yang tidak diinginkan)
  2. Acara tidak dapat ditugaskan secara langsung. Dalam hal ini, itu tidak akan memunculkan kesalahan sebelumnya yang telah saya tunjukkan dengan mengesampingkan perilaku.
  3. Tidak seorang pun di luar kelas Anda yang dapat mengangkat acara.
  4. Acara dapat dimasukkan dalam deklarasi antarmuka, sedangkan bidang tidak bisa

Catatan:

EventHandler dinyatakan sebagai delegasi berikut:

public delegate void EventHandler (object sender, EventArgs e)

Dibutuhkan pengirim (tipe objek) dan argumen acara. Pengirim adalah null jika berasal dari metode statis.

Contoh ini, yang menggunakan EventHandler<ArgsSpecial>, bisa juga ditulis menggunakan EventHandler.

Rujuk di sini untuk dokumentasi tentang EventHandler

faby
sumber
7
Semuanya tampak hebat sampai saya menemukan "Tidak ada seorang pun di luar kelas Anda yang dapat mengangkat acara." Apa artinya? Tidak bisakah ada yang menelepon RaiseEventselama metode panggilan memiliki akses ke instance animaldalam kode yang menggunakan acara?
dance2die
11
@Sung Events hanya bisa dinaikkan dari dalam kelas, mungkin saya belum jelas menjelaskannya. Dengan peristiwa, Anda dapat memanggil fungsi yang membangkitkan peristiwa (enkapsulasi), tetapi hanya dapat dibangkitkan dari dalam kelas yang mendefinisikannya. Beri tahu saya jika saya tidak jelas.
faby
1
"Acara tidak dapat ditugaskan secara langsung." Kecuali saya mengerti Anda salah, ini tidak benar. Berikut ini sebuah contoh: gist.github.com/Chiel92/36bb3a2d2ac7dd511b96
Chiel ten Brinke
2
@faby, Maksud Anda meskipun acara ini dinyatakan sebagai publik, saya masih tidak bisa melakukannya animal.Run(this, new ArgsSpecial("Run faster");?
Pap
1
@ChieltenBrinke Tentu saja acara ini dapat ditugaskan di dalam anggota kelas ... tetapi tidak sebaliknya.
Jim Balter
94

Selain sifat sintaksis dan operasional, ada juga perbedaan semantik.

Delegasi, secara konseptual, templat fungsi; yaitu, mereka menyatakan suatu kontrak yang harus dipatuhi oleh suatu fungsi untuk dipertimbangkan dari "tipe" delegasi.

Acara mewakili ... baik, acara. Mereka dimaksudkan untuk memperingatkan seseorang ketika sesuatu terjadi dan ya, mereka mematuhi definisi delegasi tetapi mereka bukan hal yang sama.

Bahkan jika mereka persis hal yang sama (secara sintaksis dan dalam kode IL) masih akan tetap ada perbedaan semantik. Secara umum saya lebih suka memiliki dua nama yang berbeda untuk dua konsep yang berbeda, bahkan jika mereka diimplementasikan dengan cara yang sama (yang tidak berarti saya suka memiliki kode yang sama dua kali).

Jorge Córdoba
sumber
8
Deskripsi delegasi yang sangat baik.
Sampson
1
Jadi dapatkah kita mengatakan bahwa suatu acara adalah jenis delegasi yang "istimewa"?
Pap
Saya tidak mengerti maksud Anda. Anda dapat menggunakan delegasi untuk 'mengingatkan seseorang ketika sesuatu terjadi'. Mungkin Anda tidak akan melakukan itu, tetapi Anda bisa dan karena itu bukan properti yang melekat pada acara.
steve
@Jorge Córdoba contoh delegasi dan acara delegasi adalah pemilik dan acara koran (Berlangganan atau berhenti berlangganan) dan beberapa orang membeli koran dan beberapa orang tidak membeli koran berarti pemilik surat kabar tidak dapat memaksa setiap orang untuk membeli koran, maksud saya benar atau salah?
Rahul_Patil
37

Berikut ini adalah tautan lain yang bagus untuk dirujuk. http://csharpindepth.com/Articles/Chapter2/Events.aspx

Secara singkat, pengambilan dari artikel - Acara adalah enkapsulasi atas delegasi.

Kutipan dari artikel:

Misalkan acara tidak ada sebagai konsep di C # /. NET. Bagaimana kelas lain berlangganan suatu acara? Tiga opsi:

  1. Variabel delegasi publik

  2. Variabel delegasi yang didukung oleh properti

  3. Variabel delegasi dengan metode AddXXXHandler dan RemoveXXXHandler

Opsi 1 jelas mengerikan, untuk semua alasan normal kami membenci variabel publik.

Opsi 2 sedikit lebih baik, tetapi memungkinkan pelanggan untuk secara efektif menimpa satu sama lain - itu akan terlalu mudah untuk menulis someInstance.MyEvent = eventHandler; yang akan menggantikan penangan acara yang ada daripada menambahkan yang baru. Selain itu, Anda masih perlu menulis properti.

Opsi 3 pada dasarnya adalah acara yang memberi Anda, tetapi dengan konvensi yang dijamin (dihasilkan oleh kompiler dan didukung oleh bendera tambahan di IL) dan implementasi "gratis" jika Anda senang dengan semantik yang diberikan acara seperti lapangan kepada Anda. Berlangganan dan berhenti berlangganan dari acara dienkapsulasi tanpa mengizinkan akses sewenang-wenang ke daftar penangan acara, dan bahasa dapat membuat segalanya lebih mudah dengan memberikan sintaksis untuk deklarasi dan berlangganan.

vibhu
sumber
Penjelasan yang bagus dan ringkas. Terima kasih
Pap
Ini lebih merupakan perhatian teoritis daripada apa pun, tetapi FWIW saya selalu merasa seperti "Opsi 1 buruk karena kami tidak suka variabel publik" argumen bisa menggunakan klarifikasi sedikit lebih. Jika dia mengatakan itu karena "praktik OOP buruk", secara teknis suatu public Delegatevariabel akan mengekspos "data", tetapi Delegatesejauh pengetahuan saya, OOP tidak pernah menyebut konsep apa pun seperti (itu bukan "objek" atau "pesan") ,.
jrh
Walaupun saya juga ingin memberikan saran yang lebih praktis, jika Anda berada dalam situasi di mana Anda ingin memastikan bahwa hanya ada satu penangan, membuat AddXXXHandlermetode Anda sendiri dengan private Delegatevariabel mungkin merupakan pilihan yang baik. Dalam hal ini Anda dapat memeriksa untuk melihat apakah pawang sudah diatur, dan bereaksi dengan tepat. Ini juga bisa menjadi pengaturan yang baik jika Anda membutuhkan objek yang memegang Delegateuntuk dapat menghapus semua penangan ( eventtidak memberi Anda cara untuk melakukan ini).
jrh
7

CATATAN: Jika Anda memiliki akses ke C # 5.0 Unleashed , baca "Batasan Penggunaan Utusan Delegasi" di Bab 18 berjudul "Acara" untuk memahami lebih baik perbedaan di antara keduanya.


Selalu membantu saya untuk memiliki contoh yang sederhana dan konkret. Jadi, ini satu untuk komunitas. Pertama saya tunjukkan bagaimana Anda bisa menggunakan delegasi sendirian untuk melakukan apa yang dilakukan Acara untuk kami. Lalu saya tunjukkan bagaimana solusi yang sama akan bekerja dengan contoh EventHandler. Dan kemudian saya jelaskan mengapa kita TIDAK ingin melakukan apa yang saya jelaskan pada contoh pertama. Posting ini terinspirasi oleh sebuah artikel oleh John Skeet.

Contoh 1: Menggunakan delegasi publik

Misalkan saya memiliki aplikasi WinForms dengan satu kotak drop-down. Drop-down terikat ke List<Person>. Di mana Orang memiliki properti Id, Nama, Nama Panggilan, Warna Rambut. Pada formulir utama adalah kontrol pengguna kustom yang menunjukkan properti orang itu. Ketika seseorang memilih seseorang di drop-down label di pembaruan kontrol pengguna untuk menunjukkan properti orang yang dipilih.

masukkan deskripsi gambar di sini

Inilah cara kerjanya. Kami memiliki tiga file yang membantu kami menyatukan ini:

  • Mediator.cs - kelas statis menampung delegasi
  • Form1.cs - formulir utama
  • DetailView.cs - kontrol pengguna menampilkan semua detail

Berikut adalah kode yang relevan untuk masing-masing kelas:

class Mediator
{
    public delegate void PersonChangedDelegate(Person p); //delegate type definition
    public static PersonChangedDelegate PersonChangedDel; //delegate instance. Detail view will "subscribe" to this.
    public static void OnPersonChanged(Person p) //Form1 will call this when the drop-down changes.
    {
        if (PersonChangedDel != null)
        {
            PersonChangedDel(p);
        }
    }
}

Inilah kontrol pengguna kami:

public partial class DetailView : UserControl
{
    public DetailView()
    {
        InitializeComponent();
        Mediator.PersonChangedDel += DetailView_PersonChanged;
    }

    void DetailView_PersonChanged(Person p)
    {
        BindData(p);
    }

    public void BindData(Person p)
    {
        lblPersonHairColor.Text = p.HairColor;
        lblPersonId.Text = p.IdPerson.ToString();
        lblPersonName.Text = p.Name;
        lblPersonNickName.Text = p.NickName;

    }
}

Akhirnya kami memiliki kode berikut di Form1.cs kami. Di sini kita Memanggil OnPersonChanged, yang memanggil kode apa saja yang berlangganan delegasi.

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    Mediator.OnPersonChanged((Person)comboBox1.SelectedItem); //Call the mediator's OnPersonChanged method. This will in turn call all the methods assigned (i.e. subscribed to) to the delegate -- in this case `DetailView_PersonChanged`.
}

Baik. Jadi begitulah cara Anda membuatnya bekerja tanpa menggunakan acara dan hanya menggunakan delegasi . Kami hanya menempatkan delegasi publik ke dalam kelas - Anda dapat membuatnya statis atau tunggal, atau apa pun. Bagus.

NAMUN, NAMUN, NAMUN, kami tidak ingin melakukan apa yang baru saja saya jelaskan di atas. Karena bidang publik buruk karena banyak, banyak alasan. Jadi apa saja pilihan kita? Seperti yang dijelaskan oleh John Skeet, berikut adalah opsi kami:

  1. Variabel delegasi publik (ini adalah apa yang baru saja kita lakukan di atas. Jangan lakukan ini. Saya baru saja memberi tahu Anda mengapa ini buruk)
  2. Tempatkan delegasi ke properti dengan get / set (masalah di sini adalah bahwa pelanggan dapat saling menimpa - sehingga kami dapat berlangganan banyak metode untuk delegasi dan kemudian kami dapat secara tidak sengaja mengatakan PersonChangedDel = null, menghapus semua langganan lainnya. Masalah lain yang tetap ada di sini adalah karena pengguna memiliki akses ke delegasi, mereka dapat meminta target dalam daftar doa - kami tidak ingin pengguna eksternal memiliki akses kapan harus meningkatkan acara kami.
  3. Variabel delegasi dengan metode AddXXXHandler dan RemoveXXXHandler

Opsi ketiga ini pada dasarnya adalah apa yang diberikan oleh suatu peristiwa kepada kita. Ketika kami mendeklarasikan EventHandler, itu memberi kami akses ke delegasi - tidak secara publik, bukan sebagai properti, tetapi karena hal ini kami sebut acara yang baru saja menambah / menghapus pengakses.

Mari kita lihat seperti apa program yang sama, tetapi sekarang menggunakan Acara alih-alih delegasi publik (Saya juga mengubah Mediator kami menjadi singleton):

Contoh 2: Dengan EventHandler alih-alih delegasi publik

Penengah:

class Mediator
{

    private static readonly Mediator _Instance = new Mediator();

    private Mediator() { }

    public static Mediator GetInstance()
    {
        return _Instance;
    }

    public event EventHandler<PersonChangedEventArgs> PersonChanged; //this is just a property we expose to add items to the delegate.

    public void OnPersonChanged(object sender, Person p)
    {
        var personChangedDelegate = PersonChanged as EventHandler<PersonChangedEventArgs>;
        if (personChangedDelegate != null)
        {
            personChangedDelegate(sender, new PersonChangedEventArgs() { Person = p });
        }
    }
}

Perhatikan bahwa jika Anda F12 pada EventHandler, itu akan menunjukkan kepada Anda bahwa definisi tersebut hanyalah sebuah delegasi umum dengan objek "pengirim" tambahan:

public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

Kontrol Pengguna:

public partial class DetailView : UserControl
{
    public DetailView()
    {
        InitializeComponent();
        Mediator.GetInstance().PersonChanged += DetailView_PersonChanged;
    }

    void DetailView_PersonChanged(object sender, PersonChangedEventArgs e)
    {
        BindData(e.Person);
    }

    public void BindData(Person p)
    {
        lblPersonHairColor.Text = p.HairColor;
        lblPersonId.Text = p.IdPerson.ToString();
        lblPersonName.Text = p.Name;
        lblPersonNickName.Text = p.NickName;

    }
}

Akhirnya, inilah kode Form1.cs:

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
        Mediator.GetInstance().OnPersonChanged(this, (Person)comboBox1.SelectedItem);
}

Karena EventHandler ingin dan EventArgs sebagai parameter, saya membuat kelas ini hanya dengan satu properti di dalamnya:

class PersonChangedEventArgs
{
    public Person Person { get; set; }
}

Semoga itu menunjukkan kepada Anda sedikit tentang mengapa kami memiliki acara dan bagaimana mereka berbeda - tetapi secara fungsional sama - seperti delegasi.

Trevor
sumber
Sementara saya menghargai semua pekerjaan baik dalam posting ini dan saya senang membaca sebagian besar, saya masih merasa satu masalah tidak ditangani - The other problem that remains here is that since the users have access to the delegate, they can invoke the targets in the invocation list -- we don't want external users having access to when to raise our events. Di versi terbaru Mediator, Anda masih dapat menelepon OnPersonChangekapan pun Anda memiliki referensi ke singleton. Mungkin Anda harus menyebutkan bahwa Mediatorpendekatan itu tidak mencegah perilaku tertentu, dan lebih dekat ke bus peristiwa.
Ivaylo Slavov
6

Anda juga dapat menggunakan acara dalam deklarasi antarmuka, tidak demikian untuk delegasi.

Paul Hill
sumber
2
@surfen Interface dapat berisi acara, tetapi bukan delegasi.
Alexandr Nikitin
1
Apa sebenarnya maksud Anda? Anda dapat memiliki Action a { get; set; }di dalam definisi antarmuka.
Chiel ten Brinke
6

Benar-benar kesalahpahaman antara acara dan delegasi !!! Delegasi menentukan JENIS (seperti class, atau interfacetidak), sedangkan acara hanya semacam ANGGOTA (seperti bidang, properti, dll). Dan, sama seperti anggota lainnya, acara juga memiliki tipe. Namun, dalam hal acara, jenis acara harus ditentukan oleh delegasi. Misalnya, Anda TIDAK BISA mendeklarasikan peristiwa dari jenis yang ditentukan oleh antarmuka.

Sebagai penutup, kita dapat melakukan Pengamatan berikut : jenis acara HARUS ditentukan oleh delegasi . Ini adalah hubungan utama antara acara dan delegasi dan dijelaskan dalam bagian II.18 Mendefinisikan peristiwa dari ECMA-335 (CLI) Partisi Saya ke VI :

Dalam penggunaan umum, TypeSpec (jika ada) mengidentifikasi delegasi yang tanda tangannya cocok dengan argumen yang diteruskan ke metode api acara.

Namun, fakta ini TIDAK menyiratkan bahwa suatu peristiwa menggunakan bidang delegasi dukungan . Sebenarnya, suatu peristiwa dapat menggunakan bidang dukungan dari berbagai jenis struktur data pilihan Anda. Jika Anda mengimplementasikan suatu acara secara eksplisit dalam C #, Anda bebas untuk memilih cara Anda menyimpan penangan acara (perhatikan bahwa penangan acara adalah contoh dari jenis acara , yang pada gilirannya adalah wajib merupakan jenis delegasi --- dari Pengamatan sebelumnya) ). Tetapi, Anda bisa menyimpan event handler tersebut (yang merupakan contoh delegasi) dalam struktur data seperti a Listatau a Dictionaryatau yang lain, atau bahkan dalam bidang delegasi pendukung. Tapi jangan lupa bahwa TIDAK wajib Anda menggunakan bidang delegasi.

Miguel Gamboa
sumber
4

Peristiwa di .net adalah kombinasi yang ditunjuk dari metode Tambahkan dan metode Hapus, yang keduanya mengharapkan beberapa jenis delegasi tertentu. Baik C # maupun vb.net dapat membuat kode secara otomatis untuk metode tambah dan hapus yang akan menentukan delegasi untuk menahan langganan acara, dan menambah / menghapus delegasi yang diteruskan ke / dari delegasi berlangganan tersebut. VB.net juga akan menghasilkan kode secara otomatis (dengan pernyataan RaiseEvent) untuk memohon daftar langganan jika dan hanya jika tidak kosong; untuk beberapa alasan, C # tidak menghasilkan yang terakhir.

Perhatikan bahwa walaupun umum untuk mengelola langganan acara menggunakan delegasi multicast, itu bukan satu-satunya cara untuk melakukannya. Dari perspektif publik, calon pelanggan acara perlu tahu cara memberi tahu objek bahwa ia ingin menerima acara, tetapi tidak perlu tahu mekanisme apa yang akan digunakan penerbit untuk mengangkat acara tersebut. Perhatikan juga bahwa sementara siapa pun yang mendefinisikan struktur data acara di .net tampaknya berpikir harus ada sarana publik untuk meningkatkannya, baik C # maupun vb.net tidak menggunakan fitur itu.

supercat
sumber
3

Untuk mendefinisikan tentang acara dengan cara sederhana:

Acara adalah REFERENSI untuk seorang delegasi dengan dua batasan

  1. Tidak dapat dipanggil secara langsung
  2. Tidak dapat menetapkan nilai secara langsung (mis. EventObj = delegateMethod)

Di atas dua adalah titik lemah untuk delegasi dan ditangani jika terjadi. Contoh kode lengkap untuk menunjukkan perbedaan dalam fiddler ada di sini https://dotnetfiddle.net/5iR3fB .

Alihkan komentar antara Event dan Delegasi dan kode klien yang memanggil / menetapkan nilai untuk didelegasikan untuk memahami perbedaannya

Ini kode inline.

 /*
This is working program in Visual Studio.  It is not running in fiddler because of infinite loop in code.
This code demonstrates the difference between event and delegate
        Event is an delegate reference with two restrictions for increased protection

            1. Cannot be invoked directly
            2. Cannot assign value to delegate reference directly

Toggle between Event vs Delegate in the code by commenting/un commenting the relevant lines
*/

public class RoomTemperatureController
{
    private int _roomTemperature = 25;//Default/Starting room Temperature
    private bool _isAirConditionTurnedOn = false;//Default AC is Off
    private bool _isHeatTurnedOn = false;//Default Heat is Off
    private bool _tempSimulator = false;
    public  delegate void OnRoomTemperatureChange(int roomTemperature); //OnRoomTemperatureChange is a type of Delegate (Check next line for proof)
    // public  OnRoomTemperatureChange WhenRoomTemperatureChange;// { get; set; }//Exposing the delegate to outside world, cannot directly expose the delegate (line above), 
    public  event OnRoomTemperatureChange WhenRoomTemperatureChange;// { get; set; }//Exposing the delegate to outside world, cannot directly expose the delegate (line above), 

    public RoomTemperatureController()
    {
        WhenRoomTemperatureChange += InternalRoomTemperatuerHandler;
    }
    private void InternalRoomTemperatuerHandler(int roomTemp)
    {
        System.Console.WriteLine("Internal Room Temperature Handler - Mandatory to handle/ Should not be removed by external consumer of ths class: Note, if it is delegate this can be removed, if event cannot be removed");
    }

    //User cannot directly asign values to delegate (e.g. roomTempControllerObj.OnRoomTemperatureChange = delegateMethod (System will throw error)
    public bool TurnRoomTeperatureSimulator
    {
        set
        {
            _tempSimulator = value;
            if (value)
            {
                SimulateRoomTemperature(); //Turn on Simulator              
            }
        }
        get { return _tempSimulator; }
    }
    public void TurnAirCondition(bool val)
    {
        _isAirConditionTurnedOn = val;
        _isHeatTurnedOn = !val;//Binary switch If Heat is ON - AC will turned off automatically (binary)
        System.Console.WriteLine("Aircondition :" + _isAirConditionTurnedOn);
        System.Console.WriteLine("Heat :" + _isHeatTurnedOn);

    }
    public void TurnHeat(bool val)
    {
        _isHeatTurnedOn = val;
        _isAirConditionTurnedOn = !val;//Binary switch If Heat is ON - AC will turned off automatically (binary)
        System.Console.WriteLine("Aircondition :" + _isAirConditionTurnedOn);
        System.Console.WriteLine("Heat :" + _isHeatTurnedOn);

    }

    public async void SimulateRoomTemperature()
    {
        while (_tempSimulator)
        {
            if (_isAirConditionTurnedOn)
                _roomTemperature--;//Decrease Room Temperature if AC is turned On
            if (_isHeatTurnedOn)
                _roomTemperature++;//Decrease Room Temperature if AC is turned On
            System.Console.WriteLine("Temperature :" + _roomTemperature);
            if (WhenRoomTemperatureChange != null)
                WhenRoomTemperatureChange(_roomTemperature);
            System.Threading.Thread.Sleep(500);//Every second Temperature changes based on AC/Heat Status
        }
    }

}

public class MySweetHome
{
    RoomTemperatureController roomController = null;
    public MySweetHome()
    {
        roomController = new RoomTemperatureController();
        roomController.WhenRoomTemperatureChange += TurnHeatOrACBasedOnTemp;
        //roomController.WhenRoomTemperatureChange = null; //Setting NULL to delegate reference is possible where as for Event it is not possible.
        //roomController.WhenRoomTemperatureChange.DynamicInvoke();//Dynamic Invoke is possible for Delgate and not possible with Event
        roomController.SimulateRoomTemperature();
        System.Threading.Thread.Sleep(5000);
        roomController.TurnAirCondition (true);
        roomController.TurnRoomTeperatureSimulator = true;

    }
    public void TurnHeatOrACBasedOnTemp(int temp)
    {
        if (temp >= 30)
            roomController.TurnAirCondition(true);
        if (temp <= 15)
            roomController.TurnHeat(true);

    }
    public static void Main(string []args)
    {
        MySweetHome home = new MySweetHome();
    }


}
Venkatesh Muniyandi
sumber
2

Delegasi adalah pointer fungsi tipe-aman. Acara adalah implementasi dari pola desain penerbit-pelanggan menggunakan delegasi.

Weidong Shen
sumber
0

Jika Anda memeriksa Bahasa Intermediate, Anda akan tahu .net compiler convert delegate to class disegel di IL dengan beberapa fungsi built-in, seperti invoke, beginInvoke, endInvoke, dan delegate class yang diwarisi dari kelas lain, mungkin disebut "SystemMulticast". Saya kira Event adalah kelas anak dari Delegasi dengan beberapa properti tambahan.

Perbedaan antara instance acara dan delegasi adalah, Anda tidak dapat menjalankan acara di luar deklarasi. Jika Anda mendeklarasikan acara di kelas A, Anda hanya dapat menjalankan acara ini di kelas A. Jika Anda mendeklarasikan delegasi di Kelas A, Anda dapat menggunakan delegasi ini di mana saja. Saya pikir ini adalah perbedaan utama di antara mereka

Shawn L
sumber