Michael27 29 Newbie Poster

This tutorial is about extension methods in c#

What is an extension method

Sometimes it is necessary to add functionality to a library for which you do not own the source code and where using inheritance to subclass functionality is not viable. This problem can be overcome with the careful use of C# 3.0 extension methods.

They allow you to extend new functionality for existing data types, that includes classes, structure or interfaces, without modifying the code of the type itself.
Introduced in the version 3.0 of the framework, before this you could modify the class only by inheriting from the existing types and adding functionality in a subclass.
If the inherited class was sealed that was not possible, with extensions this was possible, you could add functionality to sealed types.

They are used extensively in the language-integrated query (LINQ), methods such as Select, Where and OrderBy are added to the IEnumerable and generic IEnumerable(T) interfaces.

****Limitations ****

Extension methods do not modify the extended class. They are defined externally and these definitions cannot be used to override existing methods of the type. An extension method will never be called if it has the same signature as an existing class member.

It is important that the principle of encapsulation is not violated by extension methods. To prevent this, extension methods do not have access to any private members of the extended class. They may only work with externally visible members.

It is possible to create two or more extension methods with identical signatures. If two extension methods with matching signatures are visible for the same base class, the code will not compile. This problem can be circumvented by defining the extension methods in separate namespaces and ensuring only one of the namespaces is referenced in a using directive in any single code file.

Creating Extension Methods

Syntax for creating extension methods is this

public static result-type name(this obj-type obj, type1 param1, ..., typeX paramX)

To signify that the new member is an extension method, the first argument must be of the type being modified and must be preceded by the "this" keyword.
The result-type specifies the type that will be returned by the extension method. This is identical to the return type of any other method declaration. The first parameter includes two elements; obj-type is the name of the type that will be extended by the method and obj will contain the object when a call is made. The remaining parameters are those that will be included in any call to the method. These are optional.

Although an extension method is accessed as if it where an instance method of the extended type, it must actually be defined as a static member of a static class.

Example demonstration

Lets add new method to the string data type, string is sealed and can't be sub-classed, so lets see. Lets create a new console application(File -> New Project -> select console application and give it a name, press ok).

All extension must be declared as static within a static class, create a new class

public static class MyExtensionMethod
{
}

Create the new extension method inside the class, note the use of [il]this[/il] as the parameter of the method

public static void OutputToConsole(this string s)
{
    Console.WriteLine(s);
}

We now have an extension method, it is visible as an instance member for all strings.
Lets test this

string testString = "Hello, world.";
testString.OutputToConsole();  

The new method appears in Intellisense as method icon with the blue arrow down.

Adding parameters
As with other methods extension allow you to use more that one parameters, important part is only first parameter must be marked with this keyword. To demonstrate, we can modify our method to accept two parameters. These will be outputted to the console as a prefix and a suffix.

public static void OutputToConsole(this string s, string prefix, string suffix)
{
    Console.WriteLine("{0}{1}{2}", prefix, s, suffix);
}

and usage

string testString = "Hello, world.";
testString.OutputToConsole("[", "]");   // Outputs "[Hello, world.]"

Extension Methods and Inheritance

When an extension method is applied to a base class, all of its subclasses are also affected.
In this case, we will modify the existing extension method so that it is applied to the Object class, rather than the String class. As every class and structure is derived from System.Object, every class and structure will receive the new member.

Modify the extension method as follows:

public static void OutputToConsole(this object o)
{
    Console.WriteLine(o);
}

At this time, the program will still compile and execute because the string that we are using is a subclass of System.Object.

string testString = "Hello, world.";
testString.OutputToConsole();           // Outputs "Hello, world."

int testInt = 99;
testInt.OutputToConsole();              // Outputs "99"

object testObject = new object();
testObject.OutputToConsole();           // Outputs "System.Object"

Extension Methods and Interfaces

One of the more interesting uses of extension methods is the extending of interfaces. When an extension method is created with the first parameter referring to an interface, all types that implement the interface receive the new method.

This provides a manner for attaching real functionality to an interface, rather than providing a signature to be implemented by each class individually. The main limitation is that the extension method may only access members of the interface.

To demonstrate, add the interface shown below to the console application. This interface represents the individual products in a stock inventory system.

public interface IProduct
{
    string StockCode { get; set; }
    int QuantityInStock { get; set; }
    double Price { get; set; }
}

Implement it in a class

class Product : IProduct
{
    public string StockCode { get; set; }
    public int QuantityInStock { get; set; }
    public double Price { get; set; }
}

Finally, we can add an extension method to the IProduct interface. Add this within the existing MyExtensionMethods class:

public static double StockValue(this IProduct product)
{
    return product.Price * product.QuantityInStock;
}

As the Product class implements the IProduct interface, the new StockValue method is automatically available. Modify the Main method as follows to show the method's operation:

Product p = new Product {StockCode = "RAM", QuantityInStock = 100, Price = 49.99};
double stockValue = p.StockValue();
stockValue.OutputToConsole();           // Outputs "4999"

Conclusion

Extension methods can be very useful. However, because the code for extension methods is held separately from the classes that use them, they can significantly impact the readability of the code. For this reason, it is advisable to only use extension methods where no other option is viable. You should not use extension methods to modify your own assemblies simply to avoid creating a new version of a library.