我正在与 C# 中的 Action Delegates 一起工作,希望能更多地了解它们并思考它们可能有用的地方。
有没有人使用过 Action Delegate,如果有,为什么?或者你能举一些可能有用的例子吗?
这是一个小例子,展示了 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();
}
}
那么你可以做的一件事是如果你有一个开关:
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 扩展方法。
MSDN 说:
Array.ForEach 方法和 List.ForEach 方法使用此委托对数组或列表的每个元素执行操作。
除此之外,您可以将它用作接受 1-3 个参数而不返回任何值的通用委托。
您可以对短事件处理程序使用操作:
btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
我曾经在一个项目中使用过这样的动作委托:
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()}
};
它所做的只是针对一种控件存储一个操作(方法调用),以便您可以将表单上的所有控件清除回默认值。
有关如何使用 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);
}
希望这可以帮助
我在处理非法跨线程调用时使用它例如:
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
我将它用作事件处理程序中的回调。当我引发事件时,我传入一个以字符串为参数的方法。这是事件引发的样子:
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;
}
这样我可以调用从事件处理程序传递的方法,并带有一些参数来更新数据。我用它来向用户请求一些信息。
我们在测试中使用了很多 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; }
}