C# Tutorial

C# Tutorial C# First Application C# Variables C# Data Types C# Operators C# Keywords

C# Control Statement

C# If Statements C# Switch Statements C# for Loop C# While Loop C# do While loop C# Jump Statements C# Function C# functions with out variable

C# Arrays

C# Arrays

C# Function

C# Function call by value C# Call by reference C# Passing array to function C# Multidimensional Arrays C# Jagged Arrays C# Params C# Array Class C# Command Line Arguments

C# Object Class

C# Object and Classes C# Constructors C# Destructor C# this Keyword C# static field C# static class C# Static Constructor C# Structs C# enum C# Properties

C# Inheritance

C# Inheritance C# Multilevel Inheritance C# Aggregation C# Member overloading C# Method Overriding C# Base

C# Polymorphism

C# Polymorphism C# Sealed

C# Abstraction

C# Abstraction C# Interface

C# Namespace

C# Namespace C# Access Modifiers C# Encapsulation

C# Strings

C# String

C# Misc

C# Design Patterns Dictionary in C# Boxing and Unboxing in C# Ref and Out in C# Serialization in C# Dispose and Finalize in C# CONSOLE LOG IN C# Get File extension in C# Insert query in c# Difference Between List and Dictionary in C# Getters and Setters in C# Extension Methods in C# Insert query in c# CONSOLE LOG IN C# Get File extension in C# Random.NextDouble() Method in C# Binary Search in C# Difference between Delegates and Interfaces in C# Double.IsFinite() Method in C# Index Constructor in C# Abstraction in C# Basic OOPS Concepts In C# Queue.CopyTo() Method in C# single.compareto() method in C# C# Throw Exception in Constructor DECODE IN C# file.setlastwritetimeutc() method in C# Convert Object to List in C# convert.ToSByte(string, IFormatProvider) Method in C# C# Declare Delegate in Interface console.TreatControl C As Input property in C# Copying the queue elements to 1-D Array in C# Array.Constrainedcopy() Method in C# C# in and out Char.IsLetterOrDigit() method in C# Debugging in C# decimal.compare() method in C# Difference between Console.Read and Console.Readline in C# Metadata in C# C# Event Handler Example Default Interface Methods in C# Difference between hashtable and dictionary in C# C# program to implement IDisposable Interface Encapsulation in C# SortedList.IndexOfVaalue(Object) Method in C# Hash Maps in C# How to clear text files in C# How to Convert xls to xlsx in C# Foreach loop in C# FIFO in C# How to handle null exception in C# Type.Is Instance Of Type() Method in C# How to add data into MySQL database using C# How to use angular js in ASP net Csharp decimal.compare() method in Csharp Difference between Console.Read and Console.Readline in Csharp How to Implement Interface in Csharp char.IsUpper() Method in C# Index Of Any() Method in C# Quantifiers in C# C# program to Get Extension of a Given File C# Error Logging C# ENCRIPTION Can we create an object for Abstract Class in C# Console.CursorVisible in C# SortedDictionary Implementation in C# C# Hash Table with Examples Setting the Location of the Label in c# Collections in c# Virtual Keyword in C# Reverse of string in C# String and StringBuilder in C# Encapsulation in C# SortedList.IndexOfVaalue(Object) Method in C# Hash Maps in C# How to clear text files in C# How to Convert xls to xlsx in C# Foreach loop in C# FIFO in C# How to handle null exception in C# Type.Is Instance Of Type() Method in C# How to add data into MySQL database using C# How to use angular js in ASP net Csharp decimal.compare() method in Csharp Difference between Console.Read and Console.Readline in Csharp How to Implement Interface in Csharp char.IsUpper() Method in C# Index Of Any() Method in C# Quantifiers in C# C# program to Get Extension of a Given File Difference between ref and out in C# Singleton Class in C# Const And Readonly In Csharp BinaryReader and BinaryWriter in C# C# Attributes C# Delegates DirectoryInfo Class in C# Export and Import Excel Data in C# File Class in C# FileInfo Class in C# How to Cancel Parallel Operations in C#? Maximum Degree of Parallelism in C# Parallel Foreach Loop in C# Parallel Invoke in C# StreamReader and StreamWriter in C# TextReader and TextWriter in C# AsQueryable() in C# Basic Database Operations Using C# C# Anonymous Methods C# Events C# Generics C# Indexers C# Multidimensional Indexers C# Multithreading C# New Features C# Overloading of Indexers Difference between delegates and events in C# Operator overloading in C# Filter table in C# C# Queue with Examples C# Sortedlist With Examples C# Stack with Examples C# Unsafe Code File Handling in C# HashSet in C# with Examples List Implementation in C# SortedSet in C# with Examples C# in Depth Delegates and Events in C# Finally Block in C# How to Split String in C# Loggers in C# Nullable Types in C# REVERSE A STRING IN C# TYPE CASTING IN C# What is Generics in C# ABSTRACT CLASS IN C# Application of pointer in C# Await in c# READONLY AND CONSTANT IN C# Type safe in C# Types of Variables in c# Use of delegates in c# ABSTRACT CLASS IN C# Application of pointer in C# Await in c# READONLY AND CONSTANT IN C# Type safe in C# Types of Variables in c# Use of delegates in c# ABSTRACT CLASS IN C# Application of pointer in C# Await in c# READONLY AND CONSTANT IN C# Type safe in C# Types of Variables in c# Use of delegates in c# Atomic Methods Thread Safety and Race Conditions in C# Parallel LINQ in C# Design Principles in C# Difference Between Struct And Class In C# Difference between Abstraction and Encapsulation in C# Escape Sequence Characters in C# What is IOC in C# Multiple Catch blocks in C# Appdomain in C# Call back methods in C# Change Datetime format in C# Declare String array in C# Default Access Specifier in c# Foreach in LINQ C# How to compare two lists in C# How to Convert String to Datetime in c# How to get only Date from DateTime in C# Ispostback in asp net C# JSON OBJECT IN C# JSON STRINGIFY IN C# LAMBDA FUNCTION IN C# LINQ Lambda Expression in C# Microservices in C# MSIL IN C# Reference parameter in C# Shadowing(Method hiding) in C# Solid principles in C# Static Members in C# Task run in C# Transaction scope in C# Type Conversion in c# Unit of Work in C# Unit Test Cases in c# User Defined Exception in c# Using Keyword in C# Var Keyword in C# What is gac in C#

C# Delegates

Methods can be treated as first-class citizens in C# thanks to delegates, which also let you send methods as parameters, return methods from other methods, and store methods in variables. In C#, delegates offer a means of implementing callback mechanisms and event handling.

Delegates are types in C# that represent references to methods with specific signatures. It enables you to define a reference to a method and use the delegate to call it. Delegates are essential for loose coupling and separation of responsibilities in your codebase.

They are accommodating when you need to give one portion of your code a mechanism to call a method located in another part without explicitly understanding the details of the function.

Knowing Why Delegates Are Needed:

Imagine that you have a class that executes various actions, and you wish to enable clients of that class to alter specific aspects of the operation. Without delegates, you must create interfaces or base classes, override methods, and create strict code structures. By allowing customers to pass in methods to be executed inside the class, delegates offer a more flexible way to do this modification.

Syntax and Delegate Declaration

Creating and Declaring Delegates:

A delegate type defines the method signature referenced when creating or declaring a delegate. The methods that can be assigned to the delegate are modeled after the delegate type. The delegate keyword can be used to create a delegate.

Delegate Declaration Syntax:

The following is the syntax for a delegate declaration:

delegate returnType DelegateName(parameterList);

In this case, DelegateName is the name of the delegate type, returnType is the return type of the methods that the delegate can reference, and parameterList specifies the parameters of the methods.

The amount and types of parameters a method must have are specified in the delegate signature, along with the return types. If the delegate represents a method with a return value, it additionally provides the return type. The signature of a method assigned to a delegate must match that of the delegate.

Delegate Instantiation

The process of creating instances of delegate types and coupling them with methods is known as delegation. Delegates allow you to dynamically reference methods and call those methods from the delegate instance. Delegate instantiation in C# offers a versatile method for implementing callback mechanisms and event handling.

Assigning Methods to Delegates:

By making an instance of the delegate type and supplying the method as an argument, you can assign methods to delegates. The method's signature must match the defined signature of the delegate. You can use the delegate instance to call the method after assigning it to the delegate.

Instantiating Delegates with Method References:

Creating a delegate instance and associating it with a method is called delegate instantiation. Here's an example of how to instantiate a delegate with a method reference:

using System;

public delegate void MyDelegate(string message);

public class ProgramExample

{

    public static void Main()

    {

        MyDelegate myDelegate = new MyDelegate(MethodToInvoke);

        myDelegate("Hello World");

    }

    public static void MethodToInvoke(string message)

    {

        Console.WriteLine(message);

    }

}

Output:

C# Delegates

This code defines a delegate named MyDelegate, creates an instance of the delegate using the MethodToInvoke method, and then invokes the delegate with the message "Hello World" The MethodToInvoke method simply prints the provided message to the console.

Multicast Delegates and Combing Methods:

Multicast delegates, or delegates that can refer to many methods are created using the C# language. This is helpful when invoking several methods using a single delegate invocation. Use the += operator to combine methods in a multicast delegate. All the methods the delegate references are called in the order they were combined when the delegate is activated.

using System;

public delegate void MultiDelegate(string message);

public class Program

{

    public static void Main()

    {

        MultiDelegate multiDelegate = Method1;

        multiDelegate += Method2;

        multiDelegate("Multicast delegates");

    }

    public static void Method1(string message)

    {

        Console.WriteLine($"Method1: {message}");

    }

    public static void Method2(string message)

    {

        Console.WriteLine($"Method2: {message}");

    }

}

Output:

C# Delegates

In this example, the multiDelegate is created and combined with methods Method1 and Method2. When the delegate is invoked, both methods are called.

Invoking Delegates

Executing the methods referred to by the delegate instances is invoking delegates. Once a delegate is connected to one or more methods, you can use the delegate instance to invoke those methods. This makes it possible to implement delegate-based callbacks and dynamic method invocation.

Depending on the needs of your application, delegate invocation can be carried out synchronously or asynchronously.

Synchronous Invocation

When a delegate is called synchronously, the caller thread holds off on continuing until the delegate methods have finished running. When calling delegates, this is what happens by default.

using System;

public delegate void MyDelegate();

public class Program

{

    public static void Main()

    {

        MyDelegate myDelegate = MethodToInvoke;

        myDelegate(); // Synchronously invoke the delegate

        Console.WriteLine("Delegate invocation completed.");

    }

    public static void MethodToInvoke()

    {

        Console.WriteLine("MethodToInvoke executed.");

    }

}

In this example, the myDelegate is invoked synchronously, and the output order will be:

C# Delegates

Asynchronous Invocation:

When using asynchronous delegate invocation, the caller thread can continue while the delegate methods execute in their threads. This can help with parallel processing and boost efficiency.

To directly call the methods that the delegate has referenced, use the Invoke method of the delegate. It is beneficial when dealing with asynchronous operations or needing to regulate invocation.

using System;

public delegate int CalculationDelegate(int a, int b);

public class Program

{

    public static void Main()

    {

        CalculationDelegate addDelegate = Add;

        CalculationDelegate subtractDelegate = Subtract;

        int result1 = addDelegate.Invoke(10, 5); // Explicitly invoke using Invoke method

        int result2 = subtractDelegate(10, 5);   // Implicit invocation

        Console.WriteLine($"Add result: {result1}");

        Console.WriteLine($"Subtract result: {result2}");

    }

    public static int Add(int a, int b)

    {

        return a + b;

    }

    public static int Subtract(int a, int b)

    {

        return a - b;

    }

}

Output:

C# Delegates

In this example, the Invoke method explicitly invokes the addDelegate, while the subtractDelegate is invoked implicitly. Both approaches yield the same results.

Delegate Use Cases

Delegate functions provide solid and adaptable techniques to manage various software development problems. The following are some common uses for delegates:

1. Managing an event with delegates:

In event-driven programming, delegates are frequently used to implement event-handling techniques. Events are a means through which things can alert other objects to the occurrence of interesting events so that they can react appropriately. You can specify and control the methods called when an event is triggered using delegates.

using System;

public delegate void EventHandler(object sender, EventArgs e);

public class Button

{

    public event EventHandler Click;

    public void OnClick()

    {

        Click?.Invoke(this, EventArgs.Empty);

    }

}

public class Program

{

    public static void Main()

    {

        Button button = new Button();

        button.Click += Button_Click;

        // Simulate a button click

        button.OnClick();

    }

    private static void Button_Click(object sender, EventArgs e)

    {

        Console.WriteLine("Button clicked!");

    }

}

Output:

C# Delegates

In this example, the ''Button'' class specifies a 'Click' event using an event handler ('EventHandler') to manage subscribers. The 'Click' event is raised, and the subscribed methods (event handlers) are called when the button is pressed.

2. Delegate-based callback mechanisms:

A valuable tool for creating callback systems is the delegate. With callbacks, you may choose a method that will be executed once a particular operation or event has finished. Delegates allow you to pass methods as arguments to other methods, enabling flexible and adaptable behavior.

using System;

public delegate void CallbackDelegate(int result);

public class Calculator

{

    public void PerformCalculation(int a, int b, CallbackDelegate callback)

    {

        int result = a + b;

        callback(result);

    }

}

public class Program

{

    public static void Main()

    {

        Calculator calculator = new Calculator();

        CallbackDelegate callback = DisplayResult;

        calculator.PerformCalculation(24, 15, callback);

    }

    private static void DisplayResult(int result)

    {

        Console.WriteLine($"Calculation result: {result}");

    }

}

Output:

C# Delegates

The ''PerformCalculation'' method of the ''Calculator'' class here accepts a delegate (''CallbackDelegate'') as an argument. This delegate stands for a callback method that will be carried out following the calculation.

3. The Role of Delegates in Design Pattern Implementation:

Delegate participation is crucial when implementing design patterns that require dynamic behavior or modification. For instance, the Strategy Pattern calls for establishing a family of algorithms, isolating each algorithm in a different class, and allowing these classes to be used interchangeably. This flexibility can be achieved with delegated authority.

using System;

public delegate void SortingStrategy(int[] array);

public class BubbleSort

{

    public void Sort(int[] array)

    {

        // Bubble sort implementation

        int n = array.Length;

        for (int i = 0; i < n - 1; i++)

        {

            for (int j = 0; j < n - i - 1; j++)

            {

                if (array[j] > array[j + 1])

                {

                    int temp = array[j];

                    array[j] = array[j + 1];

                    array[j + 1] = temp;

                }

            }

        }

    }

}

public class QuickSort

{

    public void Sort(int[] array)

    {

        // Quick sort implementation

        QuickSortRecursive(array, 0, array.Length - 1);

    }

    private void QuickSortRecursive(int[] array, int low, int high)

    {

        if (low < high)

        {

            int pivot = Partition(array, low, high);

            QuickSortRecursive(array, low, pivot - 1);

            QuickSortRecursive(array, pivot + 1, high);

        }

    }

    private int Partition(int[] array, int low, int high)

    {

        int pivot = array[high];

        int i = (low - 1);

        for (int j = low; j < high; j++)

        {

            if (array[j] < pivot)

            {

                i++;

                int temp = array[i];

                array[i] = array[j];

                array[j] = temp;

            }

        }

        int temp1 = array[i + 1];

        array[i + 1] = array[high];

        array[high] = temp1;

        return i + 1;

    }

}

public class Sorter

{

    private SortingStrategy _strategy;

    public Sorter(SortingStrategy strategy)

    {

        _strategy = strategy;

    }

    public void Sort(int[] array)

    {

        _strategy(array);

    }

}

public class Program

{

    public static void Main()

    {

        int[] array = { 5, 2, 8, 1, 7 };

        SortingStrategy bubbleSort = new BubbleSort().Sort;

        Sorter sorter = new Sorter(bubbleSort);

        sorter.Sort(array);

        Console.WriteLine("Sorted using Bubble Sort:");

        foreach (var num in array)

        {

            Console.Write(num + " ");

        }

        Console.WriteLine();

        SortingStrategy quickSort = new QuickSort().Sort;

        sorter = new Sorter(quickSort);

        sorter.Sort(array);

        Console.WriteLine("Sorted using Quick Sort:");

        foreach (var num in array)

        {

            Console.Write(num + " ");

        }

    }

}

Output:

C# Delegates

The ''Sorter'' class takes a sorting strategy delegate as a parameter in this example. Different sorting algorithms (strategies) are implemented as separate classes, and their ''Sort'' methods are assigned to delegate instances. This approach enables the dynamic selection of sorting algorithms at runtime.

Delegate Chaining and Invocation List

Delegate chaining enables the creation of a series of method calls that can be called collectively by combining several methods into a single delegate instance. This functionality offers delegate-based programming scenarios flexibility and extensibility.

Combining Multiple Methods in a Delegate:

A delegate instance that has references to several methods is created by delegation chaining. These methods don't have to be of the same type as the delegate's signature; they can also be of different kinds. All chained methods are executed in the order they were introduced when the delegate is called.

Example:

using System;

public delegate void MyDelegate(string message);

public class Program

{

    public static void Method1(string message)

    {

        Console.WriteLine($"Method1: {message}");

    }

    public static void Method2(string message)

    {

        Console.WriteLine($"Method2: {message}");

    }

    public static void Main()

    {

        MyDelegate delegateChain = Method1;

        delegateChain += Method2; // Combine Method1 and Method2

        delegateChain("Delegate Chaining");

    }

}

Output:

C# Delegates

Exploring the Invocation List:

The invocation list of a delegate contains references to the chained methods. You can access this list using the ''GetInvocationList()'' method, which returns an array of delegates representing the individual methods.

Example:

using System;

public delegate void MyDelegate(string message);

public class Program

{

    public static void Method1(string message)

    {

        Console.WriteLine($"Method1: {message}");

    }

    public static void Method2(string message)

    {

        Console.WriteLine($"Method2: {message}");

    }

    public static void Main()

    {

        MyDelegate delegateChain = Method1;

        delegateChain += Method2; // Combine Method1 and Method2

        Delegate[] invocationList = delegateChain.GetInvocationList();

        foreach (var method in invocationList)

        {

            MyDelegate individualDelegate = (MyDelegate)method;

            individualDelegate("Individual delegate!");

        }

    }

}

Output:

C# Delegates

Invoking Delegates in Sequence:

When a delegate with a chain of methods is invoked, each method in the invocation list is executed sequentially. If any method throws an exception, the subsequent methods are not invoked.

Example:

using System;

public delegate void MyDelegate();

public class Program

{

    public static void Method1()

    {

        Console.WriteLine("Method1");

    }

    public static void Method2()

    {

        throw new Exception("Exception in Method2");

    }

    public static void Method3()

    {

        Console.WriteLine("Method3");

    }

    public static void Main()

    {

        MyDelegate delegateChain = Method1;

        delegateChain += Method2;

        delegateChain += Method3;

        try

        {

            delegateChain();

        }

        catch (Exception ex)

        {

            Console.WriteLine($"Exception: {ex.Message}");

        }

    }

}

Output:

C# Delegates

Predefined Delegates

Predefined delegates in C# are built-in .NET Framework-provided delegate classes that let you encapsulate functions with specific signatures. These preconfigured delegates make it easier to declare and use delegates by removing the requirement to develop unique delegate types for frequent use cases. The 'System' namespace contains predefined delegates, frequently used in various programming tasks.

Using Action and Func for Common Scenarios:

1. Action Delegates: The 'Action' delegate is a built-in delegate symbolizing a method without a return value. It can accept up to 16 different sorts of input parameters. Action delegates are frequently utilized to encapsulate a method that does an action or has a side effect without returning a value.

Example:

Action<string> printMessage = (message) => Console.WriteLine(message);

printMessage("Hello, Action!");

2. Func Delegates: The 'Func' delegate is a predefined delegate representing methods with return values. Func delegates can accept up to 16 input parameters and have a return type as the last parameter. There are multiple Func delegate types with different numbers of input parameters and return types ('Func<TResult>', 'Func<T, TResult>', 'Func<T1, T2, TResult>', and so on).

Example:

Func<int, int, int> add = (a, b) => a + b;

int result = add(3, 5); // result = 8

Advantages of Using Action and Func:

1. Concise Syntax: Action and Func provide a succinct syntax for defining and utilizing delegates without explicitly declaring bespoke delegate types.

2. Type Safety: Using specified delegates minimizes the possibility of runtime mistakes by ensuring type safety at compile time.

3. Simplified Delegate Usage: Action and Func make building several delegate types for different method signatures unnecessary, simplifying delegate usage.

4. Readability: Especially for straightforward circumstances, the usage of Action and Func can make the code more understandable and expressive.

Common Scenarios for Action and Func:

1. Handling Events: Action delegates come in handy when you need to do actions in response to events without returning a value.

2. Callback Functions: For callback functions where you want to run a method and get the result, func delegates are frequently utilized.

3. Parallel and Multithreading: In parallel and multithreaded contexts, Action and Func are frequently used to encapsulate jobs and actions that must be carried out concurrently.

4. LINQ Expressions: LINQ expressions include Func delegates, which let you perform actions on data collections.

5. Error Handling: Action and Func can be used to group activities that handle errors or exceptions.