Title: Use lambda expressions in C#
Lambda expressions are basically just a shorthand notation for making an anonymous method. There are a couple of formats, the simplest of which has the following syntax.
x => expression
Here expression is an expression involving the variable x. For example, the following code defines an anonymous function that takes a parameter x and returns x squared.
x => x * x
These are called lambda expressions because the thing to the right of the => operator is an expression that returns a value.
The following code shows how a program could pass this anonymous method into the method CalculateValue.
CalculateValue(x => x * x);
For this to work, the CalculateValue method must take as a parameter a method that takes a number as a parameter and that returns another number. Visual Studio infers the data types of the parameter x and the returned result. The following code shows how you might defined CalculateValue.
private void CalculateValue(Func<int, float> function)
{
...
}
In this case, CalculateValue expects as a parameter a method that takes an int as a parameter and that returns a float. The anonymous method shown earlier can meet those requirements.
If you want to include more than one parameter in lambda expressions, you must enclose the parameters in parentheses. For example, the following code shows the declaration of CalculateValue method that expects as a parameter a method that takes two int parameters and that returns a float.
private void CalculateValue(Func<int, int, float> act)
{
...
}
The following code shows how the program might use a lambda expression to call this method.
CalculateValue((x, y) => x * y);
In these examples, Visual Studio infers the data types of the lambda expression's parameters. If you don't want to use inference, for example if you want to make the code easier to read, you can include the parameters' data types as in the following code.
CalculateValue((int x, int y) => x * y);
If you include the data types, then they must match those expected by the CalculateValue method. (As far as I know you can't explicitly specify the return type, although you can make the expression on the right include a cast operator so you know what data type it returns.)
For a final example, consider the previous post Use anonymous methods in C#. That example uses the following code to pass anonymous methods to the DrawGraph method.
// 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); });
}
This post's example uses the following version of the code, which uses lambda expressions to define its anonymous methods.
// Draw the appropriate graph.
private void radF1_CheckedChanged(object sender, EventArgs e)
{
DrawGraph((float x, float y) => x * x + x * y - y);
}
private void radF2_CheckedChanged(object sender, EventArgs e)
{
DrawGraph((x, y) => (y - 1 / (x * x)));
}
private void radF3_CheckedChanged(object sender, EventArgs e)
{
DrawGraph((float x, float y) => (float)(x * x +
(y - Math.Pow(x * x, 1.0 / 3.0)) *
(y - Math.Pow(x * x, 1.0 / 3.0)) - 1)
);
}
private void radF4_CheckedChanged(object sender, EventArgs e)
{
DrawGraph((float x, float y) => (float)(y - 3 * Math.Cos(x) / x));
}
This is somewhat shorter, although its unusual syntax can be more confusing. The lambda expression used by radF3_CheckedChanged is particularly complicated because it is so long. The previous version used an intermediate variable to simplify the calculation a bit.
You don't need to use lambda expressions. You can always use the longer syntax to define anonymous methods. In fact, you don't really need to use anonymous methods either. Both anonymous methods and lambda expressions are provided so you can make your code more concise if you prefer.
My next post will explain how to use statement lambdas, which will let the program simplify the complicated expression used by radF3_CheckedChanged.
Download the example to experiment with it and to see additional details.
|