• Stefan Pauwels

  • Software Engineer

Enriching a class with extra functionality without using inheritance or composition.

Have you ever worked with an external class that is closed for modification and was not intuitive to work with? Wouldn’t it be cool to enrich a class with extra functionality without using inheritance or composition? Meet extension methods in .NET. By going through a simple example step-by-step, this blog post will show you how to create your own extension method.

What are extension methods?

An extension method is bound at compile time. It allows a class to be extended with extra functionalities. This is done by creating a static function in a static class, where the this keyword is put before the class that needs to be extended.

An example in C# is LINQ. If a developer wants to use LINQ on a collection, then he needs to import the System.Linq namespace.

To make it clearer, say we want to add a Right function to the string class. The contract of the Right function is: will return a new string containing a specified number of characters from the right side of a string.

The native way to get the last 5 characters from a string in C# looks like this:

string last5Characters = input.Substring(input.Length - 5);

The same line written with a Right extension method looks like this:

string last5Characters = input.Right(5);

Why are extension methods useful?

You can add a commonly used function like Right to the string class itself instead of writing a utility class like StringUtils.Right(input, 5). This has the benefit that Right will be included in the intellisense of the editor, allowing a developer to quickly find and use this new functionality.

The function input.Right(5) replaces the built-in string.Substring(input.Length - 5), which makes the code a bit easier to read as well, because Right better explains what the function will do.

Basically, extension methods allow developers to add functionality to classes that are closed for modification, like strings or classes from an external API. But it can also be used on your own classes, for example to convert a DTO to an entity:

Label label = labelDto.ConvertToEntity()

The string.reverse example

Consider the example case below, where we want to reverse a string. It only takes three lines to do so, but if we are going to reverse many strings in one project, we might want to group these three lines into one.

To get started, we need to create a static StringExtensions class that will contain the Reverse implementation. The Reverse function takes a string as input, reverses that string, and then returns the result.

namespace Project.Extensions
{
	public static class StringExtensionMethods
	{
		public static string Reverse(this string input)
		{
			// Does not work with code points. Like \u030
			char[] chars = input.ToCharArray();
			Array.Reverse(chars );
			return new String(chars );
		}
	}
}

The most important keyword here is this. The this keyword will tell the compiler to attach the static Reverse function to the string class.

To enhance the string class with the Reverse function, the caller needs to include the namespace Project.Extensions of the static StringExtensionMethods class.

To use the Reverse utility function, implement this piece of code:

using Project.Extensions.StringExtensionMethods

namespace Project
{
	class Program
	{
		static void Main()
		{
			string input = "ogtes123";
			string output = input.Reverse();
			Console.WriteLine(output);
		}
	}
}

If you run this code snippet, the input "ogtes123" will be reversed by invoking our brand new extension method; the console will then print out "321setgo".

Conclusion

Extension methods allow developers to enhance classes with their own functions. This increases the readability of the code. In our example we have added a Reverse utility function to the string class. Hopefully, after reading this blog post, you have gained insight into the usefulness of extension methods and how to create them yourself.

For more information about extension methods, see the Microsoft C# programming guide.