Saturday, 3 September 2016

Extension Methods

Extension Methods

Open Closed Principle(OCP) states that we should design our types in such a way that it should be open for extension but closed for modification. Extension methods in C# can be thought of as a mechanism to implement the OCP for user defined types or even the primitive types and the types defined in the framework.
Extension methods allow us to extend an existing type by adding additional methods and functionality to an existing type without needing to change the code of that type(we might even not have code in most cases). Prior to the existence of extension methods, developers used to create their own types and either inherit or contain the existing type inside these types. These new types were more of the wrappers on the existing types rather than the actual extensions of these types.
For example  if we needed to have the functionality of getting the negative of an integer then I will have to wrap my integer in a custom type and then use this custom type to perform the operation.
// Old way of extending using wrapper classes
struct MyInt
{
    int value;       
 
    public MyInt(int val)
    {
        this.value = val;
    }
 
    public int Negate()
    {
        return -value;
    }
}
 
static void Main(string[] args)
{
    // Old way of using wrappers for extensions
    MyInt i = new MyInt(53);
    Console.WriteLine(i.Negate());
}
Now this approach did work but the problem is that we are not at all extending the existing type. We are creating a new type all together that is wrapping the existing type and then providing us the desired functionality.
So if we really want to extend a method we should be able to add this method Negate in the int type only and everyone should be able to call this method on int type only. No need to create another type to have this additional functionality. Extension methods provides just the same thing. Using extension methods we can write the custom functionality and can hook them with the existing types so that they can be used on those types.
To create an extension method, we need to take the following steps:
1.     Define a static class.
2.     Define a public static function in this class with the name desired as the mew method name and return value as per the functionality.
3.     Pass the parameter of type that you want to extend. The important thing here is to put a this keyword before the parameter to tell the compiler that we need to extend this type and we are not really expecting this type as argument.
So lets try to add this Negate function in the int type.

Extension Methods

Open Closed Principle(OCP) states that we should design our types in such a way that it should be open for extension but closed for modification. Extension methods in C# can be thought of as a mechanism to implement the OCP for user defined types or even the primitive types and the types defined in the framework.
Extension methods allow us to extend an existing type by adding additional methods and functionality to an existing type without needing to change the code of that type(we might even not have code in most cases). Prior to the existence of extension methods, developers used to create their own types and either inherit or contain the existing type inside these types. These new types were more of the wrappers on the existing types rather than the actual extensions of these types.
For example  if we needed to have the functionality of getting the negative of an integer then I will have to wrap my integer in a custom type and then use this custom type to perform the operation.
Hide   Copy Code
// Old way of extending using wrapper classes
struct MyInt
{
    int value;       
 
    public MyInt(int val)
    {
        this.value = val;
    }
 
    public int Negate()
    {
        return -value;
    }
}
 
static void Main(string[] args)
{
    // Old way of using wrappers for extensions
    MyInt i = new MyInt(53);
    Console.WriteLine(i.Negate());
}
Now this approach did work but the problem is that we are not at all extending the existing type. We are creating a new type all together that is wrapping the existing type and then providing us the desired functionality.
So if we really want to extend a method we should be able to add this method Negate in the int type only and everyone should be able to call this method on int type only. No need to create another type to have this additional functionality. Extension methods provides just the same thing. Using extension methods we can write the custom functionality and can hook them with the existing types so that they can be used on those types.
To create an extension method, we need to take the following steps:
1.     Define a static class.
2.     Define a public static function in this class with the name desired as the mew method name and return value as per the functionality.
3.     Pass the parameter of type that you want to extend. The important thing here is to put a this keyword before the parameter to tell the compiler that we need to extend this type and we are not really expecting this type as argument.
So lets try to add this Negate function in the int type.
Hide   Copy Code
// Extending using Extension methods
static class MyExtensionMethods
{
    public static int Negate(this int value)
    {
        return -value;
    }
}
 
static void Main(string[] args)
{
    //Using extension method
    int i2 = 53;
    Console.WriteLine(i.Negate());
}
Now using extension method let us define the methods on some existing type. Now what if we want the new method to accept some parameters. Well to do this we can define additional parameters after the first parameter that is of the type to be extended (used with this keyword . Let define one more function in int calledMultiply to see this in action.
Hide   Copy Code
// Extending using Extension methods
static class MyExtensionMethods
{
    public static int Negate(this int value)
    {
        return -value;
    }
 
    public static int Multiply(this int value, int multiplier)
    {
        return value * multiplier;
    }
}
 
static void Main(string[] args)
{
    // Passing arguments in extension methods
    int i3 = 10;
    Console.WriteLine("Passing arguments in extension methods: {0}", i3.Multiply(2));
}
Now there are two points that need to be remembered before implementing extension methods.
·         First of which is that the extension methods can only access the public properties of the type.
·         The extension method signature should not be same as an existing method of the type.
·         The extension method for a type can only be used if the namespace that contains the extension method is in scope.
·         In case we define extension methods in such a way that it overloads an existing method of the original type and the calls are getting ambiguous then the overload resolution rule will always choose the instance method over the extension method.
·         If there is some ambiguity between two extension methods then the method containing more specific arguments will get called.
If we keep the following point in mind we could really utilize the extension methods to better design and extend the types and provide better abstraction of the type. LINQ uses extension methods heavily. It is highly recommended to look at how LINQ used extension methods in conjunction with LAMBDA expression.
// Extending using Extension methods
static class MyExtensionMethods
{
    public static int Negate(this int value)
    {
        return -value;
    }
}
 
static void Main(string[] args)
{
    //Using extension method
    int i2 = 53;
    Console.WriteLine(i.Negate());
}
Now using extension method let us define the methods on some existing type. Now what if we want the new method to accept some parameters. Well to do this we can define additional parameters after the first parameter that is of the type to be extended (used with this keyword . Let define one more function in int calledMultiply to see this in action.
// Extending using Extension methods
static class MyExtensionMethods
{
    public static int Negate(this int value)
    {
        return -value;
    }
 
    public static int Multiply(this int value, int multiplier)
    {
        return value * multiplier;
    }
}
 
static void Main(string[] args)
{
    // Passing arguments in extension methods
    int i3 = 10;
    Console.WriteLine("Passing arguments in extension methods: {0}", i3.Multiply(2));
}
Now there are two points that need to be remembered before implementing extension methods.
·         First of which is that the extension methods can only access the public properties of the type.
·         The extension method signature should not be same as an existing method of the type.
·         The extension method for a type can only be used if the namespace that contains the extension method is in scope.
·         In case we define extension methods in such a way that it overloads an existing method of the original type and the calls are getting ambiguous then the overload resolution rule will always choose the instance method over the extension method.
·         If there is some ambiguity between two extension methods then the method containing more specific arguments will get called.
If we keep the following point in mind we could really utilize the extension methods to better design and extend the types and provide better abstraction of the type. LINQ uses extension methods heavily. It is highly recommended to look at how LINQ used extension methods in conjunction with LAMBDA expression.


No comments:

Post a Comment