Understanding C# 3.0 Extension Methods


As you know, once a type such as class, interface, and structure is defined and compiled into a .NET assembly, it is not possible to add new members or update existing members without opening and changing the source code and recompiling it again. In C# 3.0, Microsoft introduced a new feature called Extension Methods that enable developers to add new functionality to existing precompiled types. These types can be either .NET Framework built in types such as String and DateTime or they can be your custom types. In this tutorial I will try to give you a complete overview of extension methods.

At first glance, the extension methods feature looks quite similar to inheritance which also enables you to add functionality to existing types by extending them. However the major difference is that extension methods enable you to inject new methods to existing types without extending or inheriting them. Once you have added some extension methods to a certain type they are only available in the context of current application and they do not actually change the compiled type. This means if you will add extension methods to String class it will not change the actual String class implementation in the .NET Framework, it will only add extra functionality to String class in your application context.

Defining Extension Methods

To define extension methods you need to keep in mind the following restrictions or requirements:

  1. Extension methods must be defined within a static class.
  2. Extension method must be defined as static method.
  3. The first and only first parameter of extension method must be marked with this keyword.
  4. Extension methods should be defined in a separate namespace.
  5. Extension method can be called through the instance of the type it is extending.
  6. Extension method can also be called directly with the name of the static class in which it is defined.
  7. Extension Methods do not have access to the members of the type they are extending

To get better understanding of all the above points and to learn how to define and use extension methods including their syntax, I have created a simple .NET Console Application. In the application I have added a static class called MyExtensionMethods with its own separate namespace. The reason you should have separate namespace for classes which are defining extension methods is that this will not confuse other developers who are familiar with existing API and whoever will import your namespace can use extra methods.

namespace ExtensionMethodsNamespace 
{ 
   public static class MyExtensionMethods 
   { 
      // Define Extension Methods Here 
   } 
}

Inside MyExtensionMethods class I have defined the following four extension methods. Notice how all the methods are marked with static keyword in their declaration. Also note how the first parameter of all the methods is qualified with this keyword.

The first method LogStringMessage adds an extension method to .NET Framework built in String type because this keyword is qualified with a String type parameter. The second method DisplayDate adds an extension method to DateTime class and returns a formatted date as string. The third method DisplayDate does almost same as the second method but it has one extra parameter to ask use the custom date format. The forth method DisplayObjectFullName is added to the Object type which is the base class of all .NET types so it can be called by any .NET Framework or custom type.

public static void LogStringMessage(this String str) 
{ 
   Console.WriteLine(str); 
} 

public static string DisplayDate(this DateTime date) 
{ 
   return date.ToString("dd-MMMM-yyyy"); 
} 

public static string DisplayDate(this DateTime date, string format) 
{ 
   return date.ToString(format); 
} 

public static string DisplayObjectFullName(this Object obj) 
{ 
   return obj.GetType().FullName; 
} 

To test these methods in the main Program in Console application you need to add the reference of the above namespace with using keyword.

using ExtensionMethodsNamespace; 

class Program 
{ 
   static void Main(string[] args) 
   {
   
   } 
}

To test first method I have created a string type object message and then i have called the String type extension method LogStringMessage by using this object. You can also call extension method directly by using class name as shown in the following code block:

string message = "Extension Methods";

// Extension Method called by using type object 

message.LogStringMessage();

// Extension method called by using Class name directly 

MyExtensionMethods.LogStringMessage(message);

Similarly you can call other extension methods as shown below:

DateTime currentDate = DateTime.Now; 

// Extension Method called by using type object 

Console.WriteLine(currentDate.DisplayDate()); 
Console.WriteLine(currentDate.DisplayDate("dd MMM yyyy")); 

// Extension method called by using Class name directly 

Console.WriteLine(MyExtensionMethods.DisplayDate(currentDate)); 
Console.WriteLine(MyExtensionMethods.DisplayDate(currentDate, "dd/MM/yyyy"));

The forth method is extension method of type Object so it can be called by both String and DateTime object as shown below:

Console.WriteLine(message.DisplayObjectFullName()); 
Console.WriteLine(currentDate.DisplayObjectFullName()); 

Until now we are only adding extension methods to existing .NET types such as String or DateTime, so to understand extension methods even more I have created another file in the Console Application with the following namespaces and classes.

namespace BookAuthorExtensionMethods
{ 
   public class BookAuthor 
   { 
      public string FirstName { get; set; } 
      public string LastName { get; set; } 
   } 

   public static class BookAuthorExtensions
   { 
      public static void DisplayFullName(this BookAuthor author) 
      { 
         // Console.WriteLine(FirstName + " " + LastName);      // ERROR 

         Console.WriteLine(author.FirstName + " " + author.LastName); 
      } 
   } 
}

The class BookAuthor is very straight forward and has only two simple properties. The class BookAuthorExtensions is defining an extension method of BookAuthor class to display author full name. Note the commented line in the above code which shows that you cannot directly access the fields or properties define in the type you are extending in this case BookAuthor. You have to access the type members using its object such as author in this case which is available in the method parameter.

To test the above extension method adds the BookAuthorExtensionMethods namespace reference in the main program and then you can test the method with simple code as shown below:

BookAuthor author = new BookAuthor(); 

author.FirstName = "Waqas"; 
author.LastName = "Anwar"; 

author.DisplayFullName();

The output of the console application is shown in the following figure.

Extension Methods

 

 

About author


User avatar

Waqas Anwar

Founder of EzzyLearning.com, Senior Consultant, Microsoft .NET and Web Technologies

Comments 2

user
Muhammad Faisal
  • 09 July 2009

Thanks Buddy! Nice Article!

user
mukesh kumar
  • 14 February 2011

why do we use extension method?

Add Comment