C# – Action delegates

When I am browsing the source code of my team, I see a lot of styles writing Action delegate. It makes me really interesting that my team has made use of this delegate to write more beautiful, shorter and sometimes… messy code. Therefore I would like to extract and reform some typical examples from our source code to this blog to show how Action delegate could be used in real application. According to MSDN, Action delegate encapsulates a method that has a single parameter and does not return a value with this syntax

public delegate void Action<in T>(T obj)

where as
in T: The type of the parameter of the method that this delegate encapsulates and
T obj : The parameter of the method that this delegate encapsulates.

If you want to read more, you can follow this link http://msdn.microsoft.com/en-us/library/018hxwa8.aspx. In this small blog, I just want to enumerate 6 typical examples of Action which are used in my team.

1. Example One.

private void btnExampleOne_Click(object sender, RoutedEventArgs e)
{
	Action<string> PrintString = new Action<string>(PrintStringToConsole);
	List<string> names = new List<string>() { "Example One","W", "A", "S", "T" };
	names.ForEach(PrintString);
	btnExampleOne.IsEnabled = false;
}
private void PrintStringToConsole(string name)
{
	txtResult.Text += Environment.NewLine + name;
}

The Example One shows a typical example of Action with data type in C# version before 3.0. I define a function (PrintStringToConsole) with a single paramter and define an Action delegate to encapsulate this parameter then call this action in foreach loop. You can replace data type “string” with any other data type which you want to apply the Action.

2. Example Two

private void btnExampleTwo_Click(object sender, RoutedEventArgs e)
{
	List<string> names = new List<string>() { "Example Two", "W", "A", "S", "T" };
	names.ForEach(x =>
	{
		txtResult.Text += Environment.NewLine;
		txtResult.Text += x;
	});
	btnExampleTwo.IsEnabled = false;
}

This example doesn’t do anything different to the first one. But with the help of Lambda Expression, I can define the function intern the foreach loop which make it easier to follow if the function is short and really complex to follow if the function is too long. Believe me, I have met a long long loo…ng function with this art of Action delegate and I really forgot what I was reading before going into the foreach loop. So don’t make your collegueas angry with this coding style.

3. Example Three

private void btnExampleThree_Click(object sender, RoutedEventArgs e)
{
	txtResult.Text += Environment.NewLine + "Example Three";
	Dictionary<Role, Action<Employee>> taskList = new Dictionary<Role, Action<Employee>>();
	taskList.Add(Role.Chef, Planning);
	taskList.Add(Role.Developer, Developing);
	Employee w = new Employee() { Name = "W" };
	taskList[Role.Chef](w);
	taskList[Role.Developer](w);
	btnExampleThree.IsEnabled = false;
}
private void Planning(Employee employee)
{
	txtResult.Text += Environment.NewLine +  "Employee " + employee.Name + " is on planning task";
}

private  void Developing(Employee employee)
{
	 txtResult.Text +=Environment.NewLine + "Employee " + employee.Name + " is on developing task";
}

...

enum Role
{
	Chef,
	Developer
}

class Employee
{
	public string Name { get; set; }
}

Example Three demonstrates the ability to assign approriate Action for each object according to predefined types. You can see in the example that each Role has his own Action. The Chef should plan resources, projects,cost … and the Developer does his job with programming,basic testing,writing documentation …. I can then examine an Employee with a Role and see how he behaves with this Role through the defined Action. It’s really comfortable for testing, simulating or applying Action on many objects without writing divergently specific code for each type of objects.

4. Example Four

private void btnExampleFour_Click(object sender, RoutedEventArgs e)
{
	Dictionary<Type, Action<Control>> controlDefaults = new Dictionary<Type, Action<Control>>()
	{
		{typeof(TextBox), x => ((TextBox)x).Text = "Result will be shown hier: "},
		{typeof(Button), x => ((Button)x).IsEnabled = true},
	};

	FindVisualChildren<Control>(gridMain).ToList().ForEach(x =>
		{
			if (controlDefaults.ContainsKey(x.GetType()))
				controlDefaults[x.GetType()](x);
		});            
}
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
	if (depObj != null)
	{
		for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
		{
			DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
			if (child != null && child is T)
			{
				yield return (T)child;
			}

			foreach (T childOfChild in FindVisualChildren<T>(child))
			{
				yield return childOfChild;
			}
		}
	}
}

Bases on Example Three, Example Four shows how we can easily reset all controls on form. Just declare their types with approriate action, loop through all controls and use the Action defined for them in Dictionary Set. It can not be simple and more beautiful.

5.Example Five

btnExampleFive.Click += (sender, e) =>
{
	txtResult.Text += Environment.NewLine + "Example Five" + Environment.NewLine + "Hey, hey I am an Action event";
	btnExampleFive.IsEnabled = false;
};

Again, I have a Lambda Expression for registering an Action to a click event of a button. When you are lazy to browse to Visual Studio Designer, use this way.

6. Example Six

private void btnExampleSix_Click(object sender, RoutedEventArgs e)
{
	this.Dispatcher.Invoke(new Action(() => 
		{
			txtResult.Text += Environment.NewLine + "Example Six" + Environment.NewLine + "Go back to GUI thread from another one";
			btnExampleSix.IsEnabled = false;
		}));
}

Now is the last example with an anonymous Action without any input argument which is normally used in my team for updating GUI from another Thread. Ofcourse you should replace “this” with your GUI UIElement which I discussed in this blog before http://hintdesk.com/c-wpf-copy-files-with-progress-bar-by-copyfileex-api/

This is the end of this blog. Nothing special, just enumerate some styles of Action delegate which are used in our source code. There are of course more of them but I would like to discuss some most popular ones. The source you can download here “Action delegates