# Mastering C# Part 3.2 Methods (Part-2)

## Anonymous Method

An **anonymous method** in C# is a method without a name, defined using the `delegate` keyword. It allows you to create inline methods, primarily useful in scenarios where a method implementation is required only once, such as for short event-handling or callback operations.

---

### **Syntax**

```csharp
delegate(parameter_list)
{
    // Method body
};
```

Anonymous methods must be assigned to a `delegate` type variable or used directly as a parameter for a method that expects a delegate.

---

```csharp
using System;

class Program
{
    delegate int Operation(int x, int y); // Delegate definition

    static void Main()
    {
        // Assigning an anonymous method to a delegate
        Operation add = delegate (int a, int b)
        {
            return a + b;
        };

        int result = add(5, 3);
        Console.WriteLine($"The sum is: {result}"); // Output: The sum is: 8
    }
}
```

---

### **Key Characteristics**

1. **Inline Declaration**: Anonymous methods are defined inline where they are used.
    
2. **Access to Outer Variables**: Anonymous methods can capture variables from the outer scope, known as **closures**.
    
3. **Event Handlers**: Often used to simplify event handling code.
    

---

### **Using Anonymous Methods in Event Handling**

Instead of defining a separate method for event handling, you can use an anonymous method directly:

```csharp
using System;

class Program
{
    static void Main()
    {
        Action<string> print = delegate (string message)
        {
            Console.WriteLine(message);
        };

        print("Hello, World!"); // Output: Hello, World!
    }
}
```

---

### **Capturing Variables (Closures)**

Anonymous methods can capture and use variables from the scope in which they are defined:

```csharp
using System;

class Program
{
    delegate void PrintDelegate();

    static void Main()
    {
        int count = 10;

        // Anonymous method capturing the outer variable 'count'
        PrintDelegate print = delegate
        {
            Console.WriteLine($"Count is: {count}");
        };

        print(); // Output: Count is: 10

        count = 20;
        print(); // Output: Count is: 20 (shows the updated value)
    }
}
```

---

### **Comparison with Lambda Expressions**

**Lambda expressions** were introduced in C# 3.0 as a more concise alternative to anonymous methods.

**Anonymous Method:**

```csharp
delegate (int a, int b)
{
    return a + b;
};
```

**Lambda Expression (Preferred):**

```csharp
(a, b) => a + b;
```

**Key Differences:**

1. **Syntax**: Lambda expressions have a shorter, more concise syntax.
    
2. **Flexibility**: Lambdas support advanced features such as expression trees and type inference.
    
3. **Preference**: Lambdas are generally preferred over anonymous methods for modern C# development.
    

---

### **Anonymous Methods and Delegates**

Anonymous methods are tightly coupled with delegates. For example:

```csharp
using System;

class Program
{
    delegate void GreetDelegate(string name);

    static void Main()
    {
        GreetDelegate greet = delegate (string name)
        {
            Console.WriteLine($"Hello, {name}!");
        };

        greet("John"); // Output: Hello, John!
    }
}
```

---

### **Limitations of Anonymous Methods**

1. **No Named Reusability**: Anonymous methods cannot be reused elsewhere since they lack a name.
    
2. **Reduced Readability**: Overusing anonymous methods can make code harder to understand.
    
3. **Verbose**: Compared to lambda expressions, anonymous methods are more verbose.
    

---

### **When to Use Anonymous Methods**

1. **Event Handling**: When a short, one-time-use method is needed for an event.
    
2. **Temporary Delegates**: For scenarios where defining a named method would be overkill.
    
3. **Testing and Prototyping**: Quick method implementations during development.
    

---

## Partial Methods in C#

**Partial methods** allow optional method declarations and implementations in `partial` classes or `partial` structs. These methods enable flexibility when splitting a class across multiple files, commonly used in scenarios like auto-generated code.

---

### **Key Points**

1. **Declaration and Implementation**:
    
    * Declared in one part of the `partial` class.
        
    * Optionally implemented in another part.
        
    * If not implemented, the declaration is removed during compilation.
        
2. **Rules**:
    
    * Must be `private` (default access).
        
    * Cannot have a return type (must be `void`).
        
    * Cannot be `virtual`, `abstract`, or `extern`.
        
3. **No Implementation? No Overhead!**
    
    * Unimplemented partial methods are ignored by the compiler.
        

---

**Declaration and Call:**

```csharp
partial class Employee
{
    partial void OnCreated(); // Declared
}

partial class Employee
{
    partial void OnCreated() // Implemented
    {
        Console.WriteLine("Employee created.");
    }

    public void Create()
    {
        OnCreated();
    }
}
```

**Usage:**

```csharp
Employee emp = new Employee();
emp.Create(); // Output: Employee created.
```

---

### **Benefits**

1. **Decoupling**: Separates declarations from implementations.
    
2. **Extensibility**: Useful for generated code customization.
    
3. **Compiler Optimization**: No performance cost for unimplemented methods.
    

---

Partial methods are a great feature for writing flexible, maintainable, and extensible code, especially in collaborative or tool-generated environments.

## Extension Methods in C#

**Extension methods** allow you to add new methods to existing types without modifying their source code or creating derived types. These are static methods that act as if they were instance methods on the extended type.

---

### **Key Points**

1. Defined in **static classes**.
    
2. The first parameter specifies the type to extend, prefixed with the `this` keyword.
    
3. Commonly used to extend framework or library classes.
    

---

```csharp
public static class StringExtensions
{
    public static bool IsPalindrome(this string str)
    {
        if (string.IsNullOrEmpty(str)) return false;
        return str.SequenceEqual(str.Reverse());
    }
}

class Program
{
    static void Main()
    {
        string word = "madam";
        Console.WriteLine(word.IsPalindrome()); // Output: True
    }
}
```

---

## Local Methods in C#

**Local methods** are methods declared inside another method. They are useful for organizing code and are accessible only within the containing method.

---

### **Key Points**

1. Declared inside another method.
    
2. Can capture and use variables from the enclosing method.
    
3. Provide better readability and encapsulation.
    

---

```csharp
class Program
{
    static void Main()
    {
        int Factorial(int number) // Local method
        {
            if (number <= 1) return 1;
            return number * Factorial(number - 1);
        }

        Console.WriteLine(Factorial(5)); // Output: 120
    }
}
```

---

### **Comparison**

| Feature | Extension Methods | Local Methods |
| --- | --- | --- |
| **Scope** | Available globally to the extended type | Limited to the enclosing method |
| **Usage** | Adds functionality to existing types | Encapsulates logic within a method |
| **Declared In** | Static classes | Any method |

---

Both extension and local methods improve code readability and modularity, offering flexibility for different scenarios.

# Delegates

A delegate is a **type-safe function pointer** in C#. It encapsulates references to methods and allows methods to be passed as parameters, stored as variables, or invoked dynamically.

### **Key Features**

* **Type-safe**: Ensures that the method signature matches the delegate signature.
    
* **Multicast**: Can invoke multiple methods if combined.
    

### **Declaration and Usage**

1. **Define a Delegate**:
    
    ```csharp
    delegate void MyDelegate(string message);
    
    ```
    
2. **Assign a Method to the Delegate**:
    
    ```csharp
    void SayHello(string message) => Console.WriteLine($"Hello, {message}!");
    MyDelegate del = SayHello;
    del("World"); // Output: Hello, World!
    
    ```
    
3. **Multicast Delegate**:
    
    ```csharp
    void SayGoodbye(string message) => Console.WriteLine($"Goodbye, {message}!");
    del += SayGoodbye;
    del("World");
    // Output:
    // Hello, World!
    // Goodbye, World!
    
    ```
    

### **Why Use Delegates?**

* Decouple methods from execution logic.
    
* Enable callbacks and event-driven programming.
    

---

## Predicates

A **Predicate** is a pre-defined delegate type in C# used specifically for methods that take one parameter and return a boolean (`bool`). It's often used for testing conditions.

### **Signature**

```csharp
public delegate bool Predicate<T>(T obj);

```

### **Practical Example**

```csharp
using System;
using System.Collections.Generic;

class Program
{
    static bool IsEven(int number) => number % 2 == 0;

    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

        // Use Predicate with FindAll
        Predicate<int> predicate = IsEven;
        List<int> evenNumbers = numbers.FindAll(predicate);

        Console.WriteLine(string.Join(", ", evenNumbers)); // Output: 2, 4
    }
}

```

---

## Action

**Action** is a pre-defined delegate type that represents a method that **does not return a value**. It can take up to 16 parameters.

### **Signature**

```csharp
public delegate void Action<T1, T2, ...>();

```

### **Example**

```csharp
using System;

class Program
{
    static void PrintMessage(string message) => Console.WriteLine(message);

    static void Main()
    {
        Action<string> action = PrintMessage;
        action("Hello, Action!"); // Output: Hello, Action!
    }
}

```

### **Common Use Case**

Use `Action` when performing operations like logging, printing, or modifying objects without returning a result.

---

## Func

**Func** is a pre-defined delegate type that represents a method with **a return value**. It can take up to 16 input parameters, and the last type parameter specifies the return type.

### **Signature**

```csharp
public delegate TResult Func<T1, T2, ..., TResult>();

```

### **Example**

```csharp
using System;

class Program
{
    static int Add(int x, int y) => x + y;

    static void Main()
    {
        Func<int, int, int> func = Add;
        int result = func(3, 4);
        Console.WriteLine(result); // Output: 7
    }
}

```

---

### **Detailed Comparison**

| **Feature** | **Purpose** | **Parameters** | **Return Type** |
| --- | --- | --- | --- |
| **Delegate** | General method reference | Customizable | Customizable |
| **Predicate** | Testing conditions | Single (T) | `bool` |
| **Action** | Perform operations without return | 0 to 16 | `void` |
| **Func** | Perform operations with return | 0 to 16 | Customizable |

---

### **Deep Dive Examples**

### Using Delegates for Callbacks

```csharp
using System;

delegate void ProcessData(int value);

class Program
{
    static void PrintDouble(int value) => Console.WriteLine(value * 2);
    static void PrintSquare(int value) => Console.WriteLine(value * value);

    static void Main()
    {
        ProcessData process = PrintDouble;
        process += PrintSquare;

        Console.WriteLine("Processing 5:");
        process(5);
        // Output:
        // 10
        // 25
    }
}

```

### Using `Action` with Lambda Expressions

```csharp
using System;

class Program
{
    static void Main()
    {
        Action<string> greet = name => Console.WriteLine($"Hi, {name}!");
        greet("Alice"); // Output: Hi, Alice!
    }
}

```

### Using `Func` to Chain Operations

```csharp
using System;

class Program
{
    static void Main()
    {
        Func<int, int, int> multiply = (x, y) => x * y;
        Func<int, int> addTen = result => result + 10;

        int result = multiply(3, 4); // 12
        result = addTen(result);    // 22

        Console.WriteLine(result);  // Output: 22
    }
}

```

### Using `Predicate` with Anonymous Methods

```csharp
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
        Predicate<int> isOdd = num => num % 2 != 0;

        List<int> oddNumbers = numbers.FindAll(isOdd);
        Console.WriteLine(string.Join(", ", oddNumbers)); // Output: 1, 3, 5
    }
}

```

---

### **Key Points to Remember**

1. **Delegates** are powerful for callbacks, event handling, and decoupling code.
    
2. **Predicate** is ideal for conditions, especially with LINQ and collections.
    
3. **Action** is useful for operations without a return value.
    
4. **Func** is versatile for operations that return a value.
