| Asynchronous Programming with async/await in C# :👈 | 👉:Memory Management in C# |
💡 Functional Programming in C# |
🧠 Functional Programming in C#
Functional programming is a paradigm that emphasizes the evaluation of mathematical functions, avoids mutable state and side effects, and treats functions as first-class citizens. In C#, a traditionally object-oriented language, functional programming concepts are supported through features like lambda expressions, Func, and Action. These are widely used in modern C#, particularly in Language Integrated Query (LINQ).
⚙️ Lambda Expressions
A lambda expression is a concise way to define an anonymous function (a function without a name). They use the => operator.
- Expression Lambda: Used for a single expression.
- Statement Lambda: Used for a block of statements enclosed in braces
{}.
Syntax: (input-parameters) => expression-or-statement-block
🔹 Example
// Expression lambda for a simple calculation
Func<int, int> square = x => x * x;
Console.WriteLine(square(5)); // Output: 25
// Statement lambda with multiple lines
Action<string> greet = name =>
{
string greeting = $"Hello, {name}!";
Console.WriteLine(greeting);
};
greet("Functional C#"); // Output: Hello, Functional C#!
🧩 Func Delegates
Func is a predefined generic delegate type that represents a method that takes one or more input parameters and returns a value. The last type parameter in the Func declaration is always the return type. It supports up to 16 input parameters.
Syntax: Func<T1, T2, ..., TResult>
🔹 Example: Func with a Lambda Expression
// Takes two integers and returns their sum
Func<int, int, int> add = (a, b) => a + b;
int sum = add(10, 20);
Console.WriteLine($"The sum is: {sum}"); // Output: The sum is: 30
// Takes a string and returns a boolean (used with LINQ's Where method)
Func<string, bool> hasLengthThree = str => str.Length == 3;
string[] words = { "cat", "dog", "elephant", "bird" };
var result = words.Where(hasLengthThree);
// result will contain "cat" and "dog"
⚡ Action Delegates
Action is a predefined generic delegate type that represents a method that takes one or more input parameters but returns no value (void). Like Func, it supports up to 16 input parameters.
Syntax: Action<T1, T2, ...>
🔹 Example: Action with a Lambda Expression
// Takes a string and prints it to the console
Action<string> printMessage = message => Console.WriteLine(message);
printMessage("This is an action delegate."); // Output: This is an action delegate.
// Takes two integers and performs an action
Action<int, int> displaySum = (x, y) => Console.WriteLine($"The sum is {x + y}.");
displaySum(5, 8); // Output: The sum is 13.
🔍 How They Enable Functional Programming in C#
- Higher-Order Functions: Functions can be passed as arguments or returned from other functions.
FuncandActiondelegates enable this, making code highly reusable. LINQ methods likeWhere,Select, andOrderByare examples of higher-order functions. - Immutability: Functional programming promotes immutability to minimize side effects and improve predictability. Although C# isn’t strictly immutable, lambda expressions and LINQ transformations produce new collections rather than modifying existing ones.
- Declarative Style: Instead of writing imperative loops like
foreach, developers can express intent using declarative LINQ expressions combined with lambdas—focusing on what to do, not how to do it.
C# supports functional programming concepts through delegates, lambda expressions, and built-in types like Func and Action. These features allow you to treat functions as first-class citizens—passing them as parameters, returning them, and composing them.
🔹 Lambda Expressions
A lambda expression is an anonymous function that can contain expressions or statements. It uses the => syntax.
Func<int, int> square = x => x * x;
Console.WriteLine(square(5)); // Output: 25
🔹 Func Delegate
Func<T, TResult> represents a method that takes parameters and returns a value.
Func<int, int, string> add = (a, b) => $"{a} + {b} = {a + b}";
Console.WriteLine(add(3, 4)); // Output: 3 + 4 = 7
🔹 Action Delegate
Action<T> represents a method that takes parameters but returns void.
Action <string> greet = name => Console.WriteLine($"Hello, {name}!");
greet("Shivshanker"); // Output: Hello, Shivshanker!
🔹 Predicate Delegate
Predicate<T> is a special Func<T, bool> used for filtering.
Predicate<int> isEven = x => x % 2 == 0;
Console.WriteLine(isEven(4)); // Output: True
✅ Best Practices
- Use lambdas for short, inline logic.
- Use
Funcfor methods that return values. - Use
Actionfor methods that perform actions without returning values. - Use
Predicatefor filtering logic. - Keep lambdas concise and readable.
📌 When to Use
- In LINQ queries for filtering, projection, and transformation.
- To pass behavior as parameters (e.g., callbacks).
- For event handling and asynchronous programming.
- To simplify code and reduce boilerplate.
🚫 When Not to Use
- For complex logic—use named methods instead.
- When readability suffers due to nested lambdas.
- In performance-critical paths—delegates may add overhead.
⚠️ Precautions
- Avoid capturing variables in lambdas that may change unexpectedly.
- Be cautious with closures and memory leaks.
- Use meaningful parameter names for clarity.
🎯 Advantages
- Concise: Reduces boilerplate code.
- Flexible: Enables higher-order functions.
- Reusable: Functions can be passed and composed.
- Declarative: Improves readability and expressiveness.
📝 Conclusion
Functional programming in C# empowers developers to write clean, expressive, and reusable code. By mastering lambdas, Func, and Action, you unlock powerful patterns for building modern and maintainable applications.
🏁 Summary
Functional programming in C# enhances code readability, reusability, and maintainability. Through lambda expressions, Func, and Action delegates, developers can adopt a declarative and expressive style while still leveraging the full power of C#’s object-oriented capabilities.
| Asynchronous Programming with async/await in C# :👈 | 👉:Memory Management in C# |