C#中Action委托的使用


132

我曾与C#中的“行动代表”一起工作,希望对他们有更多的了解,并思考他们可能在什么地方有用。

有人使用过动作代表吗,为什么?还是可以举一些可能有用的例子?

Answers:


25

MSDN说:

Array.ForEach方法和List.ForEach方法使用此委托对数组或列表的每个元素执行操作。

除此之外,您可以将其用作接受1-3个参数而不返回任何值的泛型委托。


我从没注意到Action的那些多参数版本。谢谢。
Mackenir

114

这是一个小示例,展示了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);
    }
}

注意,foreach方法迭代名称的集合并print针对集合的每个成员执行该方法。随着我们朝着更具功能性的编程风格迈进,这对我们的C#开发人员来说是一个范式转变。(有关其背后的计算机科学的更多信息,请阅读:http : //en.wikipedia.org/wiki/Map_(higher-order_function)

现在,如果您使用的是C#3,则可以使用lambda表达式进行如下修饰:

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

好吧,您可以做的一件事是,如果您有一个开关:

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

借助强大的操作功能,您可以将该开关变成字典:

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

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

...

methodList[SomeEnum](someUser);

或者,您可以更进一步:

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

....

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

仅举几个例子。当然,更明显的用途是Linq扩展方法。


太好了,我认为这可以用作决策表。
Biswanath

3
很好-这是一个重构模式“用多态替换条件”。 refactoring.com/catalog/replaceConditionalWithPolymorphism.html
David Robbins,2009年

16

您可以将操作用于短事件处理程序:

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

您也可以将它们长时间使用。btnSubmit.Click + =(sender,e)=> {MessageBox.Show(“您单击保存!”); MessageBox.Show(“您确实做到了!”); };
tdgtyugdyugdrugdr

15

我曾经在项目中使用过这样的动作委托:

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

它所做的只是存储针对一种控件类型的操作(方法调用),以便您可以清除表单上的所有控件并恢复默认值。


不错,变化不大,但是有一个叫做keyedbyTypeCollection的东西,尽管我认为它可能包裹在dictioinary(type,Object)周围。
比斯瓦纳斯

13

有关如何使用Action <>的示例。

Console.WriteLine具有满足要求的签名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);         
    }

希望这可以帮助


11

我在处理非法跨线程调用时会使用它,例如:

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

我必须感谢Reed Copsey SO用户65358的解决方案。我的完整问题答案是SO问题2587930


3

我将其用作事件处理程序中的回调。当我引发事件时,我传入一个以字符串作为参数的方法。这是该事件的发起情况:

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

方法:

   public void UpdateMethod(string SpecialCode){ }

这是事件Args的类声明:

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

这样,我可以使用一些参数调用从事件处理程序传递的方法来更新数据。我用它来向用户请求一些信息。


嗨,Sorskoot,您能否扩展一下UpdateMethod,MyEventArgs和新的BalieEventArgs一起玩的方式。Message传递给UpdateMethod的字符串是什么:UpdateMethod(“ A Message”)?哪种方法使用对象“ someDataObject”?在此先感谢
冲浪

2

我们在测试中使用了很多动作委托功能。当我们需要构建一些默认对象,以后需要对其进行修改时。我做了个小例子。要构建默认人(John Doe)对象,我们使用BuildPerson()函数。后来我们也添加了Jane Doe,但是我们修改了她的生日,名字和身高。

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; }
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.