Understanding Delegates in C# ๐Ÿš€

Understanding Delegates in C# ๐Ÿš€

ยท

3 min read

Ever wondered how to pass methods as arguments or store functions in variables, then delegates are your new best friend! So in C#, delegates allow us to reference methods and call them dynamically, making our code more flexible and reusable. Theyโ€™re like function pointers in C++, but type-safe and way cooler. ๐Ÿ˜Ž

What is a Delegate?

A delegate is a type that represents a reference to a method with a specific signature. Instead of calling methods directly, you can store them in variables and pass them around like any other object.

Types of Delegates

  • Func Delegate โ€“ A built-in delegate for methods that return a value.

  • Action Delegate โ€“ A built-in delegate for methods that return void.

  • Predicate Delegate โ€“ A built-in delegate for methods that return a boolean.

Letโ€™s see them in action! ๐Ÿš€

// Action<T> for void methods
Action<string> printAction = Console.WriteLine;
printAction("This is an Action delegate");

// Func<T, TResult> for methods that return values
Func<int, int, int> add = (x, y) => x + y;
Console.WriteLine($"Sum: {add(5, 3)}");

// Predicate<T> for methods that return a boolean
Predicate<int> isEven = num => num % 2 == 0;
Console.WriteLine(isEven(10)); // true

Logging with Delegates: A Practical Example

Now, letโ€™s see how delegates can help us log messages dynamically using different logging mechanisms. Imagine weโ€™re logging database operations for MongoDB and Couchbase. Instead of writing separate logging functions for each, we use delegates to make it flexible and reusable!

C# Logging with Delegates

using System;
using System.IO;

namespace DelegatesExplore
{
    internal static class Program
    {
        private const string CouchbaseLogFilePath = "couchbase_logs.txt";
        private const string MongoLogFilePath = "mongo_logs.txt";

        private static readonly Action<string> PrintConsoleAction = text =>
        {
            Console.WriteLine($"[Console Log] {text}");
        };

        private static readonly Action<string> PrintToFileAction = text =>
        {
            using (StreamWriter writer = new StreamWriter(MongoLogFilePath, append: true))
            {
                writer.WriteLine($"[Mongo File Log] {DateTime.Now}: {text}");
            }
        };

        private static readonly Action<string, bool> PrintCouchbaseLog = (message, success) =>
        {
            string status = success ? "Success" : "Failed";
            Console.WriteLine($"[Couchbase Log] {message} - Status: {status}");
        };

        private static readonly Action<string, bool> PrintCouchbaseFileLog = (message, success) =>
        {
            string status = success ? "Success" : "Failed";
            using (StreamWriter writer = new StreamWriter(CouchbaseLogFilePath, append: true))
            {
                writer.WriteLine($"[Couchbase File Log] {DateTime.Now}: {message} - Status: {status}");
            }
        };

        private static void ConnectToMongo(Action<string> log)
        {
            log("Inserting new record");
            log("The new record was inserted into MongoDB");
        }

        private static void ConnectToCouchbase(Action<string, bool> log)
        {
            log("Inserting unstructured record", true);
            log("The new record was inserted into Couchbase DB", true);
        }

        private static void Main()
        {
            Console.WriteLine("Welcome to Delegates Lesson!");

            // MongoDB Logging
            ConnectToMongo(PrintConsoleAction);
            ConnectToMongo(PrintToFileAction);

            // Couchbase Logging
            ConnectToCouchbase(PrintCouchbaseLog);
            ConnectToCouchbase(PrintCouchbaseFileLog);
        }
    }
}

Why Use Delegates? ๐Ÿคฉ

  • Decouples method execution โ€“ Methods donโ€™t need to be hardcoded.

  • Encourages reusability โ€“ Pass different logging strategies dynamically.

  • Supports functional programming โ€“ Functions as first-class citizens!

Final Thoughts

Delegates are powerful tools that make our C# applications more flexible and maintainable. They give us a taste of functional programming while keeping the elegance of object-oriented design. So next time you need dynamic method execution, think delegates!

Happy coding! ๐Ÿš€

ย