I was working with the Action Delgates in C# in the hope of learning more about them and thinking where they might be useful.
Has anybody used the Action Delgate, and if so why? or could you give some examples where it might be useful?
I was working with the Action Delgates in C# in the hope of learning more about them and thinking where they might be useful.
Has anybody used the Action Delgate, and if so why? or could you give some examples where it might be useful?
MSDN says:
This delegate is used by the Array.ForEach method and the List.ForEach method to perform an action on each element of the array or list.
Except that, you can use it as a generic delegate that takes 1-3 parameters without returning any value.
I used it as a callback in an event handler. When I raise the event, I pass in a method taking a string a parameter. This is what the raising of the event looks like:
SpecialRequest(this,
new BalieEventArgs
{
Message = "A Message",
Action = UpdateMethod,
Data = someDataObject
});
The Method:
public void UpdateMethod(string SpecialCode){ }
The is the class declaration of the event Args:
public class MyEventArgs : EventArgs
{
public string Message;
public object Data;
public Action<String> Action;
}
This way I can call the method passed from the event handler with a some parameter to update the data. I use this to request some information from the user.
I used the action delegate like this in a project once:
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()}
};
which all it does is store a action(method call) against a type of control so that you can clear all the controls on a form back to there defaults.
Well one thing you could do is if you have a switch:
switch(SomeEnum)
{
case SomeEnum.One:
DoThings(someUser);
break;
case SomeEnum.Two:
DoSomethingElse(someUser);
break;
}
And with the might power of actions you can turn that switch into a dictionary:
Dictionary<SomeEnum, Action<User>> methodList =
new Dictionary<SomeEnum, Action<User>>()
methodList.Add(SomeEnum.One, DoSomething);
methodList.Add(SomeEnum.Two, DoSomethingElse);
...
methodList[SomeEnum](someUser);
Or you could take this farther:
SomeOtherMethod(Action<User> someMethodToUse, User someUser)
{
someMethodToUser(someUser);
}
....
var neededMethod = methodList{SomeEnum);
SomeOtherMethod(neededMethod, someUser);
Just a couple of examples. Of course the more obvious use would be Linq extension methods.
For an example of how Action<> is used.
Console.WriteLine has a signature that satisifies 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);
}
Hope this helps
You can use actions for short event handlers:
btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");
Here is a small example that shows the usefulness of the Action delegate
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);
}
}
Notice that the foreach method iterates the collection of names and executes the print
method against each member of the collection. This a bit of a paradigm shift for us C# developers as we move towards a more functional style of programming. (For more info on the computer science behind it read this: http://en.wikipedia.org/wiki/Map_(higher-order_function).
Now if you are using C# 3 you can slick this up a bit with a lambda expression like so:
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();
}
}
I use it when I am dealing with Illegal Cross Thread Calls For example:
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();
}));
I must give credit to Reed Copsey SO user 65358 for the solution. My full question with answers is SO Question 2587930