Friday, May 11, 2012

Extension Methods ( IfNotNull methods), C#

As per MSDN, Extension methods enables you to "add" methods to existing types without creating a new derived type. They are a special kind of static method, but they are called as if they were instance methods e.g. <objectName>.<extensionMethod>( ).
Usage: Many times it happens that you want to check an object whether it is null or not before calling any of its instance method. e.g. if(parent != null) { parent.XYZ ( ); }. Now it would be better if you can simply write parent.IfNotNull ( x => x.XYZ ( ); );. Here IfNotNull is an extension method. Similarly you may wish to have a function which automatically converts first letter of a string to Uppercase, something like value.UppercaseFirstLetter( );

Implementation: Extension methods are static methods and generally you should place all static methods of your application in a separate class such as ExtensionMethods.cs. ExtensionMethod class should be a static class and all methods in this class should be public static methods. You can invoke these methods from any class in the same way as you can call instance methods. The extension method is called like an instance method, but is actually a static method. In fact the instance pointer 'this' is received as a parameter. You must specify the 'this' keyword before the appropriate parameter you want the method to be called upon.
Following code is the demonstation of InNotNull extension method.

public static class ExtensionMethods
{
      // Extension Method 1: IfNotNull
      public static U IfNotNull < T, U > (this T t, Func <T, U> function)
      {
            return t != null ? function (t) : default (U);
       }

       // Extension Method 2: UppercaseFirstLetter
       public static string UppercaseFirstLetter (this string value)
       {
             if(value.Length > 0)
             {
                   char[ ] array = value.ToCharArray( );
                   array [0] = char.ToUpper ( array [0] );
                   return new string (array);
              }
        }
}

1. IfNotNull extension method: Since this is a generic extension method i.e. it is on T, where T has no constraints, it is always available to any class or struct instance, much like Equals and GetHashCode. You'll notice that the IfNotNull method is only an obscure way to call the specified delegate on the instance, except that we check to see whether the instance is null, and don't call the delegate in that case, returning null.

2. UppercaseFirstLetter extension method: This method first checks if the string length is greater than 0 then converts first letter of that string to upper case.

Using Extension Methods:
1. Suppose you've a Child with Parent property and you want to get Name of its parent.
string parentName = child.Parent.Name;
In case either Child or Parent Name is null then you'd like the name variable to be null. You can achieve this as:
if (child != null)
{
        if(child.Parent != null)
        {
               parentName = child.Parent.Name;
         }
}

Now using the extension method you can simplify the above code as:
parentName = child.IfNotNull ( x => x.Parent ).IfNotNull ( x => x.Name);


Note that we're using lambda expression in the IfNotNull extension method making it least efficient so only use  it when you think that increased code clarity outweighs the performance loss.

2. Similar to above usage, we can use UppercaseFirstLetter method as:
string value = "myFirstLetterIsUpperCase";
value = value.UppercaseFirstLetter ( );

More Parameters: Extension methods can have many arguments other than the 'this' parameter that is required. You can even use variables 'params' arguments with extension methods, as with any method. Because extension methods are actually static methods, there is no significant performance difference between them and other methods.

Extension methods affect the syntactic representation of the source. They do not make the execution of the source code substantially different.

Sources: MSDN, Stackoverflow, DotNetPerls, Code logos, Brad Wilson.

No comments:

Post a Comment