Penggunaan C # Delegates di dunia nyata [ditutup]

16

Saya pikir saya secara konseptual memahami delegasi C #, namun, saya berjuang untuk menemukan contoh dunia nyata di mana mereka akan berguna. Bisakah Anda memberikan beberapa jawaban yang merinci bagaimana delegasi C # digunakan dalam aplikasi nyata dan masalah apa yang memungkinkan Anda untuk melakukannya.

AlexC
sumber
2
Hampir setiap kelas dalam kerangka. NET memperlihatkan beberapa rangkaian acara, jadi begitulah. Ini hanyalah cara untuk merangkum beberapa unit kerja. Sebagai contoh, katakanlah Anda menerapkan struktur pohon biner umum dalam C. Nah, satu-satunya cara untuk memesan pohon Anda adalah dengan mengambil sebagai parameter fungsi penunjuk yang tahu bagaimana melakukan penyortiran.
Ed S.

Jawaban:

16

Kode GUI menggunakan delegasi untuk menangani acara, seperti klik tombol, pergerakan jendela. Menggunakan delegasi memungkinkan Anda memiliki fungsi yang dipanggil kapan pun peristiwa itu terjadi. Contohnya adalah menautkan fungsi yang menyimpan data ke tombol "Simpan" pada antarmuka. Ketika tombol diklik itu diatur untuk menjalankan fungsi yang menyimpan data. Ini berguna dalam pemrograman GUI karena seluruh program Anda bisa menunggu pengguna untuk melakukan sesuatu dan Anda tidak memiliki cara untuk mengetahui apa yang akan mereka lakukan terlebih dahulu. Menggunakan delegasi memungkinkan fungsionalitas program Anda untuk terhubung ke UI sedemikian rupa sehingga pengguna dapat melakukan hal-hal dengan cara apa pun yang mereka inginkan.

FrustratedWithFormsDesigner
sumber
2
++ Anda benar, tapi saya masih membencinya :-) jadi bertahun-tahun yang lalu saya datang dengan ini .
Mike Dunlavey
12

Linq menggunakan Func<T>dan Action<T>mendelegasikan seluruh tempat sebagai parameter.

Ini memungkinkan Anda untuk menggunakan ekspresi lambda sebagai parameter dan menentukan tindakan yang akan diambil sebagai bagian dari daftar parameter.

Oded
sumber
12

Sebenarnya apa pun yang menggunakan Pola Pengamat kemungkinan akan menerapkan delegasi.

Baca deskripsi dan Anda mungkin akan membayangkan beberapa skenario di mana Anda akan menggunakannya. Penanganan acara GUI adalah contoh umum.

Apa namanya
sumber
+1, Pola strategi benar-benar di mana delegasi bersinar, yaitu, Anda memiliki beberapa kelas di mana beberapa metode melakukan sesuatu, tetapi Anda ingin sesuatu dapat dipertukarkan dan tanpa ketergantungan langsung, delegasi ergo. Perhatikan bahwa acara agak memenuhi kebutuhan yang sama dengan delegasi, perbedaannya adalah Anda menggunakan delegasi ketika Anda harus bereaksi pada beberapa nilai balik, sedangkan Anda hanya memecat event dan apa pun yang akan terjadi.
Homde
9

Delegasi sangat berguna dalam pemrograman asinkron.

Anda memiliki kelas yang melakukan hal-hal secara tidak sinkron dan memiliki panggilan balik. Anda dapat meminta metode delegasi dipanggil saat panggilan balik - dan implementasi kelas Anda akan melakukan logika yang dijelaskan dalam metode delegasi Anda.

James Love
sumber
9

Delegasi sangat berguna sebagai solusi untuk lubang di pola tengah . Pada dasarnya, ada banyak kasus di mana Anda ingin membungkus satu set instruksi unik di dalam sekelompok instruksi umum. Ini sangat sulit jika instruksi sebelum dan sesudah bit unik perlu berbagi status. Dengan delegasi, Anda bisa meneruskan delegasi ke suatu fungsi. Fungsi mengeksekusi bit sebelum, mengeksekusi delegasi, lalu mengeksekusi bit setelah.

Scott Whitlock
sumber
5

Di "masa lalu" bahasa non-OOP seperti Fortran dan C, sangat berguna untuk memiliki subrutin yang menerima argumen yang merupakan penunjuk ke fungsi. Misalnya, qsortfungsi ini berfungsi dengan fungsi perbandingan yang disediakan pengguna. Ada banyak subrutin untuk menyelesaikan persamaan diferensial biasa, atau untuk mengoptimalkan fungsi, dan mereka semua menggunakan pointer fungsi sebagai argumen.

Dalam sistem windowing, semua jenis panggilan balik mengikuti pola yang sama.

Di Lisp, bahkan pada hari-hari awal, ada sesuatu yang disebut "argumen fungsional" atau FUNARG, yang tidak hanya fungsi, tetapi juga mengandung konteks penyimpanan di mana ia dapat mengingat dan berinteraksi dengan bagian dari dunia luar.

Kebutuhan yang sama ada dalam bahasa OOP, kecuali ketika Anda melewati alamat fungsi Anda juga harus melewati alamat objek fungsi adalah metode. Itu dua hal yang harus Anda lewati. Jadi delegasi hanya itu, dan memungkinkan pola lama yang baik untuk tetap digunakan.

Mike Dunlavey
sumber
3

Berikut adalah contoh sederhana yang menunjukkan bagaimana delegasi yang berguna dapat membuat kode sederhana yang mengikuti prinsip KERING. Ini juga memungkinkan Anda untuk menjaga kode sangat dekat dengan tempat yang dibutuhkan.

Action<Button, Action<Button>> prepareButton = 
    (btn, nxt) => { 
        btn.Height = 32;
        btn.Width= 64;
        nxt(btn);
    };

prepareButton(myBtn1, btn => btn.Text = "A");
prepareButton(myBtn2, btn => btn.Text = "B");
prepareButton(myBtn3, btn => btn.Text = "C");

Ini adalah contoh nyata dari keuntungan yang diberikan oleh delegasi.

protected override void PageInitialize()
{
    const string selectCodeFormat = "javascript:selectCode('{0}', '{1}');";
    const string onClick = "return toggleElement(this);";

    Func<HtmlGenericControl> getElement = null;
    Action<HtmlGenericControl> setElement = null, addChild = null;
    HtmlGenericControl level1Element = null, level2Element = null, level3Element = null, level4Element = null;
    string className = null, code = null, description = null;           

    using (var records = Core.Database.ExecuteRecords("code.SocCodeTree"))
    {
        while (records.Read())
        {
            code = records.GetString("Code");
            description = records.GetString("Description"); 

            if (records.GetString("Level4") != "")
            {
                className = "Level4";
                setElement = e => level4Element = e;
                getElement = () => level4Element;
                addChild = e => level3Element.Controls.Add(e);
            }
            else if (records.GetString("Level3") != "")
            {
                className = "Level3";
                setElement = e => level3Element = e;
                getElement = () => level3Element;
                addChild = e => level2Element.Controls.Add(e);
            }
            else if (records.GetString("Level2") != "")
            {
                className = "Level2";
                setElement = e => level2Element = e;
                getElement = () => level2Element;
                addChild = e => level1Element.Controls.Add(e);
            }
            else
            {
                className = "Level1";
                setElement = e => level1Element = e;
                getElement = () => level1Element;
                addChild = e => Root.Controls.Add(e);
            }

            var child = new HtmlGenericControl("li");
            child.Attributes["class"] = className;
            var span = new HtmlGenericControl("span") { 
                InnerText = code + " - " + description + " - " 
            };
            span.Attributes["onclick"] = onClick;
            child.Controls.Add(span);
            var a = new HtmlAnchor() { 
                InnerText = "Select", 
                HRef = string.Format(selectCodeFormat, code, description) 
            };
            child.Controls.Add(a);
            setElement(new HtmlGenericControl("ul"));
            child.Controls.Add(getElement());
            addChild(child);    
        }
    }
}
Kekacauan Kekacauan
sumber
2

Pertemuan pertama saya dengan delegasi sedang memeriksa pembaruan program (windows form C # 3.5) dengan mengunduh file dari situs web saya, tetapi untuk menghindari pembaruan memeriksa mengunci seluruh program saya menggunakan delegasi dan utas untuk melakukannya secara tidak sinkron.

Ken
sumber
1

Saya telah melihat implementasi yang menarik dari pola Strategi yang menggunakan delegasi secara efektif. (yaitu strateginya adalah delegasi)

Yang saya lihat adalah pathfinding di mana algoritma untuk menemukan path adalah delegasi yang dapat (kembali) ditugaskan pada saat runtime sehingga algoritma yang berbeda dapat digunakan (BFS vs A * dll.)

Steven Evers
sumber
1

Banyak pola GoF klasik dapat diimplementasikan dengan delegasi: Misalnya, pola Komando, pola Pengunjung, pola Strategi, pola Pabrik dan pola Pengamat sering dapat diimplementasikan dengan delegasi sederhana. Kadang-kadang, kelas lebih baik (misalnya ketika perintah membutuhkan nama atau objek strategi perlu diserialisasi) tetapi dalam kebanyakan kasus, menggunakan Action<...>atau Func<...>jauh lebih elegan daripada membuat antarmuka satu metode khusus.

nikie
sumber