In this chapter, you will learn how to use anonymous methods and lambdas is C# to write flexible, concise, and reusable code. Topics covered in this chapter include creating and using anonymous methods, expressions, and statement lambdas.
Anonymous methods
Anonymous methods are also declared using the delegate
keyword. Unlike traditional delegates, however, anonymous methods do not reference existing named methods. Instead, the code to be executed is assigned directly to the delegate (a concept referred to as inline). When declaring an anonymous method, you will still use the following syntax:
delegate <returntype> <delegatename> (<parameters>);
The differences appear when you assign the code to be executed. The syntax for assigning a block of code to be executed by an anonymous method is as follows:
<delegate_type> <delegate_name> = delegate(<parameters>) { // Code to be executed };
Using this syntax and taking our LowerCase
method code as an example, we would write code as follows:
delegate string StringConverter(string value); StringConverter converter = delegate(string value) { System.Console.Write("Converting to lower case > "); return value.ToLower(); };
Try the example code below in Visual Studio to see the above anonymous method declaration in action:
class HelloWorld { delegate string StringConverter(string value); static void Main() { StringConverter converter = delegate(string value) { System.Console.Write("Converting to lower case > "); return value.ToLower(); }; var result = converter("This is some TEXT"); System.Console.WriteLine(result); } }
As with delegates, you can also pass anonymous methods as method parameters using the same syntax outlined earlier in the lesson, for example:
class HelloWorld { delegate string StringConverter(string value); static void DisplayText(StringConverter converter, string text) { string result = converter(text); System.Console.WriteLine($"Converted text = {result}"); } static void Main() { StringConverter converter = delegate(string value) { System.Console.Write("Converting to lower case > "); return value.ToLower(); }; DisplayText(converter, "This IS a teST."); } }
Lambdas
You can think of lambdas as anonymous methods that allow code to be written more concisely. As with delegates and anonymous methods, you will first need to declare a variable of type delegate
in which to store the lambda reference and to define the return value and parameter types using the following, now familiar, syntax:
delegate <returntype> <delegatename> (<parameters>);
Lambdas are declared using the lambda operator =>
. The left side of the operator lists the input parameters, and the right side consists of an expression or code block containing the code to be executed.
C# supports the following types of lambda:
- Expression lambda – The lambda body consists of a single expression to be executed.
- Statement lambda – The lambda body consists of a statement block enclosed in braces (
{}
) containing multiple statements.
The syntax for an expression lambda reads as follows:
(input-parameters) => expression
Note: When passing a single parameter to a lambda, the parentheses placed around the input parameters in the above syntax are optional.
A statement lambda, on the other hand, uses the following syntax:
(input-parameters) => { <statements> };
To gain an appreciation of the concise nature of lambdas, consider the following anonymous method declaration:
delegate string StringConverter(string s); StringConverter converter = delegate(string s) { return s.ToLower(); };
Using a lambda, we can implement the same behavior as follows:
delegate string StringConverter(string s); static void Main() { StringConverter converter = s => s.ToLower(); System.Console.WriteLine(converter("HELLO")); }
Before using a lambda, we started with the following code:
delegate(string s) { return s.ToLower(); };
Using a lambda has allowed us to reduce the original code to the following:
s => s.ToLower();
In the above lambda example, the right side of the lambda operator indicates that a single parameter named s
is being passed through to the expression on the right. Notice that we did not need to declare that s
is of type string
. This is because we have already declared the type in the delegate variable declaration. The expression simply returns the value after converting it to lowercase. Having declared the lambda, we would call it just like an anonymous method:
var result = converter("Some Text");
Passing multiple parameters
Our earlier lambda example used only one input parameter. If you need to pass multiple parameters to a lambda, you can do so by enclosing them in parentheses (()
). For example:
delegate string MyLambda(string s, int i, double d); static void Main() { MyLambda sample = (s, i, d) => $"Product = {s}, Count = {i}, Price = {d}"; System.Console.WriteLine(sample("Hat", 5, 20.99)); }
Passing no parameters
Alternately, a lambda that accepts no parameters is declared using empty parentheses:
delegate string SayHello(); static void Main() { SayHello hello = () => "Hello"; System.Console.WriteLine(hello()); }