Công dụng của đại biểu hành động trong C # [đã đóng]


132

Tôi đã làm việc với các Đại biểu Hành động trong C # với hy vọng tìm hiểu thêm về họ và nghĩ xem họ có thể hữu ích ở đâu.

Có ai đã sử dụng Action Delegate chưa, và nếu vậy tại sao? hoặc bạn có thể đưa ra một số ví dụ nơi nó có thể hữu ích?

Câu trả lời:


25

MSDN nói:

Đại biểu này được sử dụng bởi phương thức Array.ForEach và phương thức List.ForEach để thực hiện một hành động trên từng thành phần của mảng hoặc danh sách.

Ngoại trừ điều đó, bạn có thể sử dụng nó như một đại biểu chung có 1-3 tham số mà không trả về bất kỳ giá trị nào.


Tôi không bao giờ nhận thấy những phiên bản đa tham số của Action. Cảm ơn.
mackenir

114

Dưới đây là một ví dụ nhỏ cho thấy sự hữu ích của đại biểu Hành động

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);
    }
}

Lưu ý rằng phương thức foreach lặp lại bộ sưu tập tên và thực thi printphương thức đối với từng thành viên của bộ sưu tập. Đây là một chút thay đổi mô hình cho các nhà phát triển C # của chúng tôi khi chúng tôi hướng tới một phong cách lập trình nhiều chức năng hơn. (Để biết thêm thông tin về khoa học máy tính đằng sau nó, hãy đọc bài này: http://en.wikipedia.org/wiki/Map_(higher-order_feft) .

Bây giờ nếu bạn đang sử dụng C # 3, bạn có thể làm nổi bật lên một chút với biểu thức lambda như vậy:

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();
    }
}

68

Vâng, một điều bạn có thể làm là nếu bạn có một công tắc:

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

Và với sức mạnh hành động, bạn có thể biến công tắc đó thành một cuốn từ điển:

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

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

...

methodList[SomeEnum](someUser);

Hoặc bạn có thể đi xa hơn:

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

....

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

Chỉ là một vài ví dụ. Tất nhiên việc sử dụng rõ ràng hơn sẽ là phương pháp mở rộng Linq.


Tuyệt vời, tôi nghĩ rằng điều này có thể được sử dụng như một bảng quyết định.
Biswanath

3
Đẹp - đây là mô hình tái cấu trúc "Thay thế điều kiện bằng đa hình". refactoring.com/catalog/replaceConditableWithPolymorphism.html
David Robbins

16

Bạn có thể sử dụng các hành động cho các trình xử lý sự kiện ngắn:

btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");

Bạn có thể sử dụng chúng cho những người dài quá; btnSubmit.Click + = (người gửi, e) => {MessageBox.Show ("Bạn đã nhấp lưu!"); MessageBox.Show ("Bạn thực sự đã làm!"); };
tdgtyugdyugdrugdr

15

Tôi đã sử dụng đại biểu hành động như thế này trong một dự án một lần:

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()}
    };

mà tất cả những gì nó làm là lưu trữ một hành động (gọi phương thức) đối với một loại điều khiển để bạn có thể xóa tất cả các điều khiển trên một biểu mẫu trở lại mặc định.


Đẹp, không phải là một thay đổi lớn nhưng có một cái gì đó gọi là keyedbyTypeCollection, mặc dù tôi nghĩ rằng nó bao bọc xung quanh độc tài (loại, đối tượng), có thể.
Biswanath

13

Để biết ví dụ về cách sử dụng Hành động <>.

Console.WriteLine có chữ ký bão hòa 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);         
    }

Hi vọng điêu nay co ich


11

Tôi sử dụng nó khi tôi đang xử lý các cuộc gọi chủ đề chéo bất hợp pháp Ví ​​dụ:

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();
}));

Tôi phải cung cấp tín dụng cho người dùng Reed Copsey SO 65353 cho giải pháp. Câu hỏi đầy đủ của tôi với câu trả lời là SO Câu hỏi 2587930


3

Tôi đã sử dụng nó như một cuộc gọi lại trong một xử lý sự kiện. Khi tôi nâng sự kiện lên, tôi truyền vào một phương thức lấy một chuỗi tham số. Đây là những gì nâng cao của sự kiện này trông giống như:

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

Phương pháp:

   public void UpdateMethod(string SpecialCode){ }

Đây là khai báo lớp của sự kiện Args:

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

Bằng cách này tôi có thể gọi phương thức được truyền từ bộ xử lý sự kiện với một tham số nào đó để cập nhật dữ liệu. Tôi sử dụng điều này để yêu cầu một số thông tin từ người dùng.


Xin chào Sorskoot, bạn có thể mở rộng cách UpdateMethod, MyEventArss và BalieEventArss mới chơi cùng nhau không. chuỗi Tin nhắn được truyền vào UpdateMethod: UpdateMethod ("Tin nhắn")? Phương thức nào sử dụng đối tượng "someDataObject"? Cảm ơn trước
lướt web

2

Chúng tôi sử dụng rất nhiều chức năng đại biểu hành động trong các thử nghiệm. Khi chúng ta cần xây dựng một số đối tượng mặc định và sau đó cần sửa đổi nó. Tôi làm ví dụ nhỏ. Để xây dựng đối tượng người mặc định (John Doe), chúng tôi sử dụng BuildPerson()hàm. Sau này chúng tôi cũng thêm Jane Doe, nhưng chúng tôi sửa đổi ngày sinh và tên và chiều cao của cô ấy.

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; }
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.