Extension Methods

Extend the functionality of a type without changing its source code.

Add functionality

There may be situations when we need to extend a class or struct’s functionality. There are several approaches we could take.

Change the source code

We could go to the source code of the type and make whatever changes we need. Consider the following Printer class. Its purpose is to print the Message property in a variety of ways. If we need additional functionality, we can simply add another method or edit existing ones:

C#
using System;
namespace MainProgram
{
public class Printer
{
public string Message { get; set; }
public Printer(string message)
{
Message = message;
}
// We can change this method or add another one
public void PrintWithDashes()
{
Console.WriteLine($"###{Message}###");
}
}
}

This approach is only useful if we control the source code of the type we want to modify. This isn’t possible in most cases, because the code is likely managed by a different person, team, or company.

Extend with inheritance

Another approach we could take is to inherit the type we want to extend. In terms of our Printer class, we can create a class that inherits from Printer and add the methods and properties we need:

C#
using System;
namespace MainProgram
{
// Because we cannot change the source code of the Printer class,
// we create a different class that derives from Printer
public class StarPrinter : Printer
{
public StarPrinter(string message) : base(message)
{
}
// Here we can add additional functionality
public void PrintWithStars()
{
Console.WriteLine($"***{Message}***");
}
}
}

This approach is possible, but it’s not useful if the type we want to extend is sealed.

Extension methods

Extension methods can help when it’s impossible to change the source code or to inherit from the type we want to extend.

Consider the following example. We want to add a method to the System.String class that allows us to reverse a System.String object. We don’t have access to the source code of the System.String class, so we can’t add a new method there. We can create an extension method, however:

public static string Reverse(this string stringObject)
{
	// Implementation
}

Extension methods are static methods that have the this keyword before the first parameter. The type that comes after this is the type on which this method will be executed.

In the example above, this is followed by string, which means that the method is an extension method for string objects.

Note: Extension methods can only be hosted inside static classes, and to be able to use extension methods, we must import the namespace in which the static class resides.

C#
using System;
namespace Extensions
{
// Static class
public static class StringExtensionMethods
{
// Static method
// Look at the this keyword
public static string Reverse(this string stringObject)
{
char[] charArray = stringObject.ToCharArray();
char[] reversedArray = new char[charArray.Length];
for (int i = charArray.Length - 1, j = 0; i >= 0; i--, j++)
{
reversedArray[j] = charArray[i];
}
return new string(reversedArray);
}
}
}

Extension methods are also useful when the type we want to extend is marked with the sealed keyword. We can’t inherit from a sealed type, but we can extend it with extension methods:

C#
// Imported this namespace
// because the Person class
// is in this namespace
using MainProgram;
namespace Extensions
{
public static class PersonExtensionMethods
{
public static decimal GetMonthlySalary(this Person person)
{
return person.AnnualSalary / 12;
}
}
}