Title: Use anonymous methods in C#
My previous post Use the predefined Action, Func, and EventHandler delegate types in C# explains how to use the predefined generic Func, Action, and EventHandler delegate types to graph four functions F(x, y). It uses the following code to define the functions and call them.
// x^2 + x*y - y = 0
private float F1(float x, float y)
{
return (x * x + x * y - y);
}
// y - 1 / x^2 = 0
private float F2(float x, float y)
{
return (y - 1 / (x * x));
}
// x^2 + (y - (x^2)^1/3))^2 - 1 = 0
private float F3(float x, float y)
{
double temp = y - Math.Pow(x * x, 1.0 / 3.0);
return (float)(x * x + temp * temp - 1);
}
// y - 3 * Cos(x) / x
private float F4(float x, float y)
{
return (float)(y - 3 * Math.Cos(x) / x);
}
// Draw the appropriate graph.
private void radF1_CheckedChanged(object sender, EventArgs e)
{
DrawGraph(F1);
}
private void radF2_CheckedChanged(object sender, EventArgs e)
{
DrawGraph(F2);
}
private void radF3_CheckedChanged(object sender, EventArgs e)
{
DrawGraph(F3);
}
private void radF4_CheckedChanged(object sender, EventArgs e)
{
DrawGraph(F4);
}
The code first defines the four functions F1, F2, F3, and F4. The four CheckBox controls' CheckedChanged event handlers call the DrawGraph method, passing that method the function to graph. The DrawGraph method (which isn't really important to this example, so it's not shown here) takes as a parameter the function to draw and draws it, at one point passing the function to another method.
The fact that their names are F1, F2, F3, and F4 is a hint that the functions themselves aren't really meaningful in themselves. They are basically defined, passed into DrawGraph, and then forgotten.
Because the functions aren't used in other parts of the program, you can replace these functions with anonymous methods. An anonymous method is basically a delegate that refers to some code that doesn't have a name. You can store the delegate in a delegate variable or pass it to a method as a parameter.
The syntax for an anonymous method is:
delegate(parameters) { ...code... });
Here parameters defines any parameters the delegate should take. If the code inside the braces returns a value, it should use a return statement just like any other method.
The following code shows how this post's example uses anonymous methods to handle its CheckedChanged events.
// Draw the appropriate graph.
private void radF1_CheckedChanged(object sender, EventArgs e)
{
DrawGraph(delegate(float x, float y) {return x * x + x * y - y; });
}
private void radF2_CheckedChanged(object sender, EventArgs e)
{
DrawGraph(delegate(float x, float y) { return (y - 1 / (x * x)); });
}
private void radF3_CheckedChanged(object sender, EventArgs e)
{
DrawGraph(delegate(float x, float y)
{
double temp = y - Math.Pow(x * x, 1.0 / 3.0);
return (float)(x * x + temp * temp - 1);
});
}
private void radF4_CheckedChanged(object sender, EventArgs e)
{
DrawGraph(delegate(float x, float y)
{ return (float)(y - 3 * Math.Cos(x) / x); });
}
In this version, the event handlers pass the four functions to the DrawGraph method as anonymous methods so the program doesn't need to define the functions separately. This makes the code a bit more concise and easier to read, although the third anonymous method is a bit long. If that function were much longer, it might be better to put its code in a named method to make the code more readable.
Usually you shouldn't use an anonymous method if the method will be used in multiple places, if its code is too long, or if it would otherwise be less confusing to use a named method. Anonymous methods don't give you any real performance advantage (unlike the inline macros used by some programming languages), so you should only use them if they make the code easier to understand.
In the next post, I'll show how you can use lambda statements to make defining anonymous methods easier.
Download the example to experiment with it and to see additional details.
|