Extend classes with additional behavior without modifying them
Before we jump into creating an extension method, could someone please tell me what the heck extension methods are?
Well, let’s about we start with a nice little introduction.
Well as per MSDN, Extension methods enable you to “add” methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are static methods, but they’re called as if they were instance methods on the extended type.
You know what? That sounds good to hear, Microsoft! But let’s make some sense out of it.
Extension methods are a perfect example of Open-Closed Principle, which says — “Open for Extension, Closed for Modification”. Software entities should be open for extension but closed for modification. This simply means that an entity should be easily extendable without modifying itself.
- What it’s saying is, now you can explicitly add a new method to existing
"class String"(isn’t that something?).
- If you wanted to check if a string is a palindrome or not, you can simply create an extension method and be done with it once and for all.
But the question is how?
For everyone’s sake, we are not actually going to use yet another string palindromes example. Instead, we are going to implement something useful.
Let’s code an extension method to get the description of the
enum by its value. Believe me, I had to google this answer so many times that I decided to write this article so as to not swim across the pacific ocean full of plastic waste just to get my tuna.
First things first: “Can you make changes to the
The answer is: No, of course not! You can not make any changes to the system’s classes for that matter. Now you may argue that I can inherit
"class String" and extend additional functionality by overriding its existing methods? Well, you can’t do that either because it’s a sealed class. This means it is closed for inheritance as well.
So how do we extend the behavior of existing classes?
Have a quick look at figure 1. It’s the big picture of what we are going to do.
As you can see in the image above, there are 2 extension methods,
- first one,
“type enum”to fetch
“description”of enum values.
- Second, the extension method
GetEnumValueByDescription()which is for
“type string”to fetch the
“enum value”by their description.
Now go ahead and create an enum as shown in Listing 1 below. This is an enum of flagship phones:
In order to get the description, we are going to create an extension method on enum.
There are a few rules we need to take care of while creating an extension method.
Rule 1: Extension methods are defined as static but are called by using instance method syntax. In the following syntax, we have created a static method
Rule 2: The first parameter specifies which type for which we are creating the extension method, in this example that would be
“Enum”. The parameter is always decorated by
Rule 3: In order to access extension methods, one explicitly has to import the namespace. In order to access the following
“GetEnumDescription() method” we need to add
“using ExtensionMethod;” namespace in the caller class.
“Overriding is strictly prohibited”you can use extension methods to extend the behavior of the class or interface, but not to override the existing behavior.
Now that we are done with all the rules, let’s add some logic to this empty body. In the following listing, all I am doing is fetching the
“type enum” in line number 3 and in the next line I am searching for the custom attribute which is
“type of DescriptionAttribute” if type matched then simply return the description, if
“type is not DescriptionAttribute” then simply throw an exception.
All set, let’s see the magic. As per our diagram, let’s call this extension method in the
“class Program”In the following listing 5, we are creating a variable of type
“FlagshipSmartphone enum” with value of
“Samsung”. Then in line number 4 we are actually calling our newly created extension method with the help of the (.) dot operator.
Run the application and you should be able to see the output as figure 2.
Now that we are familiar with all the bits and pieces let’s jump into code. We are going to reuse
“GetEnumDescription()” to avoid rewriting the same logic.
- You may ask, what are we doing in listing 6?
- First, we are using the first parameter
- Then we are going to return a generic type parameter
“<T>”to make this method reusable across all the types of enums.
- As far as logic is concerned, we are looping through enums values looking for matching descriptions. Once the description matches we are simply returning that enum value if there is no enum with a matching description then we are simply throwing an exception. You can handle this the way you want but for simplicity, right now I am just throwing an exception.
Let’s go ahead and call this method in our
“class Program”. As you can see in line number 8. we are using a (.) dot operator on a string variable
iphone to call our extension method.
Let’s run this guy here! and you should be able to see an output as figure 3.
This is how you can extend the behavior of existing classes without modifying them. There are other design patterns as well you can use to achieve this but this is a shortcut you could use.
There is one more interesting thing. As it’s a user-defined static class you can also call this method directly using the class name.
There are some predefined extension methods available in C#.
If you take the following example, we have an
“int array” and we are using
“FirstOrDefault()” on the array.
But guess what? Array doesn’t have any method named
FirstOrDefault(). This is happening because
FirstOrDefault() is an extension method which can be used by any collection that is implementing
In our case, Array does implement
IEnumerable interface as per Figure 4.
As we learn in listing 8, we can directly use static class to call the extension method. So we can also rewrite the code in listing 9 with the one shown below.
Note: The first parameter is, “
this of type collection”. This means you will have to pass an
“integer array” as the first parameter to the
But it always preferred to use extension methods, I mean that’s why they are designed for.