When writing applications, you will often use ready-made libraries and classes that were written by other people and you will not have access to their source code. If you need a method that is not in a given class, you will probably not look for its author, but will try to add such a method yourself. You're probably wondering how you can do this. The first thing you probably thought was that if you need to extend a class, you need to use inheritance or composition. Also in the case of inheritance, you would have to add a new class that will inherit from the class you want to extend and in it you can add a new method and write its implementation. Of course, this method is not ideal, because you will have to create a lot of new classes and you will have to change all the calls in your code. You can also, instead of using inheritance and composition, write a new method that will accept a given class as a parameter and, based on its value, perform some action and then return the appropriate value. Is there a better solution? Yes, this is where extension methods come in handy. Learn about what extension methods are and how to use them in your code in this article.
The problem we want to solve
Suppose we have a simple problem to solve. We display a table with products, including a string field - description. This description, let's say, is stored in the database and can have a maximum size of 300 characters. However, we only want to display the first 20 characters in the table. If a given description has 20 characters or less, then we display the entire description, but if the product description has more than 17 characters, we display the first 17 characters and add the suffix "...". Thanks to this, the description can have a maximum of 20 characters. It will be nice if this solution is universal and can be used in many places, in different classes and projects. How can such a solution be implemented?
Solution 1 - Adding a regular static method to the project
It seems to me that the first, most intuitive solution is to add a new static method that will accept a string as a parameter, i.e. a description, which will then be modified if necessary and return the first 20 characters. This is what an example implementation and call might look like:
namespace App
{
class Program
{
static void Main(string[] args)
{
var description = "12345678901234567890X";
var shortDescription = StringMethods.GetTheFirstNCharacters(description, 20);
Console.WriteLine(shortDescription);
///12345678901234567...
}
}
public static class StringMethods
{
public static string GetTheFirstNCharacters(string val, int maxNumberOfCharacters)
{
if (string.IsNullOrWhiteSpace(val))
return string.Empty;
if (val.Length <= maxNumberOfCharacters)
return val;
return val.Substring(0, maxNumberOfCharacters - 3) + "...";
}
}
}
As you can see, this solution meets all the assumptions, but is it perfect? No, I think this solution can be written better, thanks to extension methods. So what should this solution look like?
Solution 2 - Using the extension method
The second solution may not be so intuitive for everyone, but I think it will be much better in this case. That is, we can use the title extension methods, thanks to which we will extend the string class with a new method that we will be able to use in our applications. Also thanks to extension methods, we can extend any class without using inheritance.
namespace App
{
class Program
{
static void Main(string[] args)
{
var description = "12345678901234567890X";
var shortDescription = description.GetTheFirstNCharacters(20);
Console.WriteLine(shortDescription);
//12345678901234567...
}
}
public static class StringExtensions
{
public static string GetTheFirstNCharacters(this string val, int maxNumberOfCharacters)
{
if (string.IsNullOrWhiteSpace(val))
return string.Empty;
if (val.Length <= maxNumberOfCharacters)
return val;
return val.Substring(0, maxNumberOfCharacters - 3) + "...";
}
}
}
As for the logic, there are no changes here, but in this case I used an extension method, thanks to which the string class was extended with a new method. You can use the GetTheFirstNCharacters method like a regular string class method. This method is also suggested by intellisense after entering a dot after the variable name. It seems to me that such a notation is much more legible and universal. You don't need to call any static methods from other classes here, you just call the extension method like any other method of the string class. Moreover, you can separate such extension methods into a separate project and use them in your other applications, if necessary.
How to write extension methods?
For a method to be an extension method, it must meet several conditions:
- It must be implemented in a static class
- The extension method must be static
- The first parameter of an extension method must be preceded by the this keyword before the name of the class it extends
Importantly, note that we do not pass the first argument to the extension method, which is preceded by the word this, because that is the type we are extending. It also calls our method on this type. This value is passed automatically.
If intellisense does not suggest the syntax, i.e. it does not show your method, then probably (if you have defined the extension method correctly) the method was written in a different namespace, so you also need to add the appropriate using in this file.
I often use such extension methods in my projects. I always stick to the convention that a given extension method is in a class called: extended type + Extensions suffix. That is, for a string, it will be a class called StringExtensions as in the example above. Such methods and the appropriate project structure increase the readability of the code.
Examples of extension methods
In C# you often come across various extension methods. You use them often and you may not even know it. Examples of such methods are LINQ methods. That is, for example, calculating the sum of an IEnumerable collection:
var myNumbers = new List<int> { 1, 2, 3 };
myNumbers.Sum();
This is what the Sum method signature looks like:
public static int Sum(this IEnumerable<int> source);
As you can see, this is a method that extends the IEnumerable class.
SUMMARY:
As you can see, extension methods can have various uses, I often use them in my projects to improve the readability of the code. Thanks to them, you can easily extend code that you do not have access to. If you want to become a .NET developer, knowledge of this topic may also be useful for you during job interviews. Recruiters like to raise the topic of extension methods, if you are interested in such issues, some time ago I prepared several articles in which you will find questions and answers to the 100 most common interview questions for the position of a junior .NET programmer. If you have any questions about this topic, please comment below or send me an e-mail :)