在C#中使用Action委托

时间:2008-12-16 11:38:42

标签: c# lambda delegates action

我正在与C#中的行动代表合作,希望能够更多地了解它们并思考它们可能有用的地方。

是否有人使用过Action Delegate,如果有,为什么?或者你能举出一些可能有用的例子吗?

9 个答案:

答案 0 :(得分: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();
    }
}

答案 1 :(得分:67)

你可以做的一件事就是如果你有一个开关:

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扩展方法。

答案 2 :(得分:25)

MSDN说:

  

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

除此之外,您可以将其用作通用委托,该委托使用1-3个参数而不返回任何值。

答案 3 :(得分:16)

您可以对短事件处理程序使用操作:

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

答案 4 :(得分:14)

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

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

它所做的就是对一种控件存储一个动作(方法调用),这样你就可以将表单上的所有控件清除回默认值。

答案 5 :(得分:13)

有关Action&lt;&gt;的示例使用。

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

希望这有帮助

答案 6 :(得分: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 Question 2587930

答案 7 :(得分: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;
    }

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

答案 8 :(得分:2)

我们在测试中使用了很多Action委托功能。当我们需要构建一些默认对象以后需要修改它。我做了一些例子。要构建默认人(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; }
    }