Sunday 12 February 2012

Extension Methods In Dot Net, C#

Sometimes we are in need to extend any class but often it is just not possible to use inheritance if you are working with a value type, a sealed class, or an interface. C# 3 introduces the idea of extension methods.

Extension methods allows an existing type to be extended with new methods without altering the definition of the original type.

SYNTAX

You cannot use any method as the extension method – it has to have the following characteristics:

  • It has to be in a non-nested, non-generic static class and therefore has to be a static method.
  • It has to have at least one parameter where the type of the first parameter will be the type that is extends.
  • The first parameter has to be prefixed with this keyword.

In final words, an extension method is a static method of a static class, where the this modifier is applied to the first parameter. The type of the first parameter will be the type that is extended.

For example:

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ', '.', '?' },
               StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }  
}

Syntax Explanation

MyExtensions class is a static class and WordCount is a static method of static class. this keyword tells that this is an extension method. Type of first parameter tells it is extending string class.

Usage

The WordCounts extension method can be called as it was an instance method of a string class, as follows:

Console.WriteLine ("Hello Extension Methods".WordCount());

or

string s = "Hello Extension Methods";
int i = s.WordCount();

Note: Extension methods are only in scope when you explicitly import the namespace into your source code with a using directive.

In your code you invoke the extension method with instance method syntax. However, the intermediate language (IL) generated by the compiler translates your code into a call on the static method. Therefore, the principle of encapsulation is not really being violated. In fact, extension methods cannot access private variables in the type they are extending.

The above function’s translation will be as follows:

Console.WriteLine (MyExtensions.WordCount("Hello Extension Methods"));

Extending Interfaces

LINQ has already extended lots of interfaces like, IEnumerable, IEnumerable<T>, IList, IList<T> etc.

A simple syntax of how to extend the interface is:

public static T First<T> (this IEnumerable<T> sequence)
{
    foreach (T element in sequence)
        return element;

    throw new InvalidOperationException ("No elements found!");
}
...
Console.WriteLine ((new int[]{23,453,345}).First());

Extension Method Chaining

Extension methods, like instance methods, provide a tidy way to chain functions. Consider the following two functions:

IList<string> strings = new List<string>();
strings.Add("Hello");
strings.Add("Extension");
strings.Add("Methods");

strings.First().WordCount();

Ambiguity and Resolution

As mentioned above, Extension Methods are only in scope when you explicitly import the namespace into your source code with a using directive. Consider the extension method WordCount, the following application must import ExtensionMethods, in order to avoid a compile-time error:

namespace TestApp
{
    using ExtensionMethods; // importing namespace
    class Test
    {
        static void Main()
        {
            Console.WriteLine ("Hello Extension Methods".WordCount());
        }
    }
}

Extension methods v.s. instance methods

As per the standard preference rule, any compatible instance method will always take precedence over the extension method. In the following example, Test’s Foo method will always take precedence even when called with an argument x of type int:

class Test
{
    public void Foo (object x) { } // This method always wins
}
static class Extensions
{
    public static void Foo (this Test t, int x) { }
}

The only way to call the extension method in this case is via normal static syntax-

Extensions.Foo(...).

Extension methods versus extension methods

If two extension methods have the same signature then the method must be called as an ordinary static method to resolve ambiguity.

If one extension method has more specific arguments, then the more specific method takes precedence. To illustrate, consider the following two classes:

static class StringExtensions
{
    public static int WordCount (this string s) {...}
}
static class ObjectExtensions
{
    public static int WordCount (this object s) {...}
}

The following code calls StringExtensions’s WordCount method:

int wordCount = "Hello Extension Methods".WordCount();

To call ObjectExtensions’s WordCount method, we must specify it explicitly:

int wordCount = (ObjectExtensions.WordCount ("Hello Extension Methods"));

No comments:

Post a Comment