Extension Methods in C#

"Adding behaviors to non-modifiable classes since 2007"

Sometimes, you encounter situations where you cannot modify a class or a piece of functionality. This could be due to:

  • Class in Another Library: The class might belong to a third-party library or a framework, and you do not have access to its source code.
  • Method Doesn’t Quite Fit: The existing methods in a class may not meet your specific needs, and you want to extend the class with additional functionality.

Example Scenario

Imagine you are working with string - it's fundamental to the language but almost completely non-extensible. You may find that the existing methods of the string class do not fully cover your requirements, and you want a way for developers to interact with the string in a way that feels natural. For instance, you might want to add formatting methods but do so in a way where you access those methods from the string class directly.

Extension Methods

What Are Extension Methods?

Extension methods allow you to "add" new methods to an existing class without modifying its source code. This is achieved by creating a static class with static methods that act as if they are part of the class you are extending.

Syntax

To create an extension method:

  1. Define a Static Class: The extension methods must be in a static class.
  2. Create a Static Method: The method you want to add must be static.
  3. Use the this Keyword on the first parameter: The first parameter of the method specifies the type that the method operates on, using the this keyword.

Example: Extending the string Class

Let’s add a method to the string class to check if a string is a palindrome.

public static class StringExtensions
{
    public static bool IsPalindrome(this string str)
    {
        if (string.IsNullOrEmpty(str))
            return false;

        string reversed = new string(str.Reverse().ToArray());
        return str.Equals(reversed, StringComparison.OrdinalIgnoreCase);
    }
}

Benefits of Extension Methods

  • Enhances Existing Classes: Allows you to add functionality to existing classes without altering their source code.
  • Improves Readability: Provides a way to use methods in a more natural and readable manner.
  • Code Organization: Keeps related extension methods together in a static class.

Nuanced example

Oftentimes, you will define interfaces in such a way that you want to narrowly define what the interface is, but still have convenient methods for developers to use. Those convenient methods are best added via extension methods.

Example

Let's say you have an interface such as:

public interface ILogger
{
    void Log(LogLevel level, string message);
}

With a logger level that might look like this:

public enum LogLevel
{
    Information,
    Warning,
    Error
}

Instead of defining an extension method for every logging level, you can define an extension method for the ILogger interface:

public static class LoggerExtensions
{
    public static void LogInformation(this ILogger logger, string message)
    {
        logger.Log(LogLevel.Information, message);
    }

    public static void LogWarning(this ILogger logger, string message)
    {
        logger.Log(LogLevel.Warning, message);
    }

    public static void LogError(this ILogger logger, string message)
    {
        logger.Log(LogLevel.Error, message);
    }
}

This keeps your API surface area small for the ILogger interface, while adding convenient methods for developers to use. Convenience makes developers happy!