Delegasi Penggunaan Tindakan dalam C # [ditutup]

132

Saya bekerja dengan Delegasi Aksi di C # dengan harapan bisa belajar lebih banyak tentang mereka dan berpikir di mana mereka mungkin berguna.

Adakah yang menggunakan Delegasi Aksi, dan jika demikian mengapa? atau bisakah Anda memberikan beberapa contoh yang mungkin bermanfaat?

Biswanath
sumber

Jawaban:

25

MSDN mengatakan:

Delegasi ini digunakan oleh metode Array.ForEach dan metode List.ForEach untuk melakukan tindakan pada setiap elemen dari array atau daftar.

Kecuali itu, Anda dapat menggunakannya sebagai delegasi umum yang mengambil 1-3 parameter tanpa mengembalikan nilai apa pun.

arul
sumber
Saya tidak pernah memperhatikan versi multi-parameter dari Action. Terima kasih.
mackenir
114

Ini adalah contoh kecil yang menunjukkan manfaat dari delegasi Action

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Action<String> print = new Action<String>(Program.Print);

        List<String> names = new List<String> { "andrew", "nicole" };

        names.ForEach(print);

        Console.Read();
    }

    static void Print(String s)
    {
        Console.WriteLine(s);
    }
}

Perhatikan bahwa metode foreach mengulang koleksi nama dan mengeksekusi printmetode terhadap masing-masing anggota koleksi. Ini sedikit perubahan paradigma bagi kami para pengembang C # saat kami bergerak ke arah gaya pemrograman yang lebih fungsional. (Untuk info lebih lanjut tentang ilmu komputer di baliknya baca ini: http://en.wikipedia.org/wiki/Map_(higher-order_function) .

Sekarang jika Anda menggunakan C # 3 Anda dapat sedikit mempercantik ini dengan ekspresi lambda seperti:

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<String> names = new List<String> { "andrew", "nicole" };

        names.ForEach(s => Console.WriteLine(s));

        Console.Read();
    }
}
Andrew Hare
sumber
68

Nah satu hal yang bisa Anda lakukan adalah jika Anda memiliki saklar:

switch(SomeEnum)
{
  case SomeEnum.One:
      DoThings(someUser);
      break;
  case SomeEnum.Two:
      DoSomethingElse(someUser);
      break;
}

Dan dengan kekuatan tindakan Anda dapat mengubah saklar itu menjadi kamus:

Dictionary<SomeEnum, Action<User>> methodList = 
    new Dictionary<SomeEnum, Action<User>>()

methodList.Add(SomeEnum.One, DoSomething);
methodList.Add(SomeEnum.Two, DoSomethingElse); 

...

methodList[SomeEnum](someUser);

Atau Anda bisa mengambil ini lebih jauh:

SomeOtherMethod(Action<User> someMethodToUse, User someUser)
{
    someMethodToUse(someUser);
}  

....

var neededMethod = methodList[SomeEnum];
SomeOtherMethod(neededMethod, someUser);

Hanya beberapa contoh. Tentu saja penggunaan yang lebih jelas adalah metode ekstensi Linq.

Alat Programmin
sumber
Hebat, saya pikir ini bisa digunakan sebagai tabel keputusan.
Biswanath
3
Bagus - ini adalah pola refactoring "Ganti Kondisional dengan Polimorfisme". refactoring.com/catalog/replaceConditionalWithPolymorphism.html
David Robbins
16

Anda dapat menggunakan tindakan untuk penangan event pendek:

btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
Aaron Powell
sumber
Anda dapat menggunakannya untuk yang lama juga; btnSubmit.Click + = (pengirim, e) => {MessageBox.Show ("Anda mengklik simpan!"); MessageBox.Show ("Anda benar-benar melakukannya!"); };
tdgtyugdyugdrugdr
15

Saya menggunakan delegasi tindakan seperti ini dalam sebuah proyek sekali:

private static Dictionary<Type, Action<Control>> controldefaults = new Dictionary<Type, Action<Control>>() { 
            {typeof(TextBox), c => ((TextBox)c).Clear()},
            {typeof(CheckBox), c => ((CheckBox)c).Checked = false},
            {typeof(ListBox), c => ((ListBox)c).Items.Clear()},
            {typeof(RadioButton), c => ((RadioButton)c).Checked = false},
            {typeof(GroupBox), c => ((GroupBox)c).Controls.ClearControls()},
            {typeof(Panel), c => ((Panel)c).Controls.ClearControls()}
    };

yang dilakukan adalah menyimpan tindakan (pemanggilan metode) terhadap jenis kontrol sehingga Anda dapat menghapus semua kontrol pada formulir kembali ke sana secara default.

Nathan W
sumber
Bagus, bukan perubahan besar tapi ada sesuatu yang disebut keyedbyTypeCollection, meskipun saya pikir itu membungkus dictioinary (tipe, Object), mungkin.
Biswanath
13

Sebagai contoh bagaimana Aksi <> digunakan.

Console.WriteLine memiliki tanda tangan yang memuaskan Action<string>.

    static void Main(string[] args)
    {
        string[] words = "This is as easy as it looks".Split(' ');

        // Passing WriteLine as the action
        Array.ForEach(words, Console.WriteLine);         
    }

Semoga ini membantu

Biner Terburuk
sumber
11

Saya menggunakannya ketika saya berurusan dengan Panggilan Lintas Thread Ilegal Misalnya:

DataRow dr = GetRow();
this.Invoke(new Action(() => {
   txtFname.Text = dr["Fname"].ToString();
   txtLname.Text = dr["Lname"].ToString(); 
   txtMI.Text = dr["MI"].ToString();
   txtSSN.Text = dr["SSN"].ToString();
   txtSSN.ButtonsRight["OpenDialog"].Visible = true;
   txtSSN.ButtonsRight["ListSSN"].Visible = true;
   txtSSN.Focus();
}));

Saya harus memberikan kredit kepada pengguna Reed Copsey SO 65358 untuk solusinya. Pertanyaan lengkap saya dengan jawaban adalah SO Pertanyaan 2587930

Ron Skufca
sumber
3

Saya menggunakannya sebagai panggilan balik dalam event handler. Ketika saya meningkatkan acara, saya mengirimkan metode mengambil string parameter. Seperti inilah penampilan acara tersebut:

SpecialRequest(this,
    new BalieEventArgs 
    { 
            Message = "A Message", 
            Action = UpdateMethod, 
            Data = someDataObject 
    });

Metode:

   public void UpdateMethod(string SpecialCode){ }

Ini adalah deklarasi kelas dari acara Args:

public class MyEventArgs : EventArgs
    {
        public string Message;
        public object Data;
        public Action<String> Action;
    }

Dengan cara ini saya dapat memanggil metode yang dilewatkan dari event handler dengan beberapa parameter untuk memperbarui data. Saya menggunakan ini untuk meminta beberapa informasi dari pengguna.

Sorskoot
sumber
Hai Sorskoot, dapatkah Anda memperluas bagaimana UpdateMethod, MyEventArgs, dan BalieEventArgs baru bermain bersama. apakah pesan string diteruskan ke UpdateMethod: UpdateMethod ("A Message")? Metode mana yang menggunakan objek "someDataObject"? Terima kasih sebelumnya
surfmuggle
2

Kami menggunakan banyak fungsi delegasi Tindakan dalam pengujian. Ketika kita perlu membangun beberapa objek default dan kemudian perlu memodifikasinya. Saya membuat sedikit contoh. Untuk membangun objek orang default (John Doe) kita menggunakan BuildPerson()fungsi. Kemudian kami menambahkan Jane Doe juga, tetapi kami memodifikasi tanggal lahir dan nama serta tinggi badannya.

public class Program
{
        public static void Main(string[] args)
        {
            var person1 = BuildPerson();

            Console.WriteLine(person1.Firstname);
            Console.WriteLine(person1.Lastname);
            Console.WriteLine(person1.BirthDate);
            Console.WriteLine(person1.Height);

            var person2 = BuildPerson(p =>
            {
                p.Firstname = "Jane";
                p.BirthDate = DateTime.Today;
                p.Height = 1.76;
            });

            Console.WriteLine(person2.Firstname);
            Console.WriteLine(person2.Lastname);
            Console.WriteLine(person2.BirthDate);
            Console.WriteLine(person2.Height);

            Console.Read();
        }

        public static Person BuildPerson(Action<Person> overrideAction = null)
        {
            var person = new Person()
            {
                Firstname = "John",
                Lastname = "Doe",
                BirthDate = new DateTime(2012, 2, 2)
            };

            if (overrideAction != null)
                overrideAction(person);

            return person;
        }
    }

    public class Person
    {
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public DateTime BirthDate { get; set; }
        public double Height { get; set; }
    }
yang jahat
sumber