What and Why?
Want to add a method to a string? Want to allow an XmlDocument to load from your Foo class? Well until now you’d have had to either derive your own class from string or XmlDocument, place a method on your Foo class or create an obscure static helper class to contain these methods, doing nothing for the cohesion of your design.
Extension methods have changed all this as they provide a mechanism to “add” a method to an existing class without having access to source code of the original class. The client code knows no difference between a conventional instance method and an extension method and methods can be added to existing classes without code needing to be recompiled unless it makes use of the new method.
C# 3.0 – Real life example
We used Team Foundation Server 2008 (TFS) for our builds and each project had the potential to build for several different clients, so each build definition would actually contain say 20 build configurations. Using the TFS API I wanted to be able to get a list of the customer configurations that a build contained so that we could select a build for an individual customer and then schedule the rest of the builds for overnight execution.
What I needed was a “GetBuildConfigurations” method on an existing IBuildServer interface. The code below is what I came up with:
public static class IBuildServerExtensions
{
public static List<string> GetBuildConfigurations(this IBuildServer server, string teamProject, string buildDefName)
{
List<string> ret = new List<string>();
// Get the build def XML
string buildFileContents = GetBuildProjectContents(server, teamProject, buildDefName);
// Find the list of configurations ready to return
XDocument doc = XDocument.Parse(buildFileContents);
if (doc.Root != null)
{
// Loop through each matching configuration and add the name to our list
...
}
return ret;
}
}
// Client Code
[WebMethod]
public string[] GetBuildConfigurationList(string teamProject, string buildDefName)
{
IBuildServer buildServer = Server.GetService(typeof(IBuildServer)) as IBuildServer; // Server is a property that returns a TeamFoundationServer object
return buildServer.GetBuildConfigurations(teamProject, buildDefName).ToArray();
}
Let’s go through the code:
- The class containing the extension method is static. It has to be this way.
- The class name follows no rules except my own naming convention.
- The extension method is static although the client code uses it as an instance method. It too has to be this way.
- The first argument is preceded by the keyword “this” and the argument type is the type that is to be extended. This is mandatory. So, if you are adding a method to a string class the code would be:
public static class StringExtension
{public static void AdditionalMethod(this string instance)
{// Do something}
}
- The rest of the method is the same as any other method.
- The client code does not deal with IBuildServerExtensions it only deals with IBuildServer.
- The client code calls the GetBuildConfigurations method as if it was part of the original IBuildServer interface definition.
Rules
- Extension methods are defined as static methods.
- Extension methods can only be declared in non-generic, non-nested static classes.
- You can extend classes or interfaces.
- More than one class can provide extension methods for the same class and can both be used by the same client code. E.g. Class1 and Class2 can both provide extension methods for string.
- Extension methods are made available by adding a reference to the containing assembly and namespace as normal.
- Existing methods can be overloaded but not overridden using extension method.
- Both an existing instance method and an extension method can have the same signature! The extension method will never be used however because the instance method will have a higher priority at compile time.
- You have no magic access to the internals of the class or interface that you are extending. You only get access to the public and internal entities as normal.
Summary
Extension methods allow you to add those much sort after missing methods to existing classes and interfaces. This is very cool but should not be mistreated. Adding methods to the wrong classes will damage your design, reputation and ultimately the code that you are working on, so as always, know your tools but don’t use a hammer all over the place.
Read more here.
Tags: Extension methods