LINQ: Creating your first Extension Method

Sep 22, 2005 • 3 minutes to read

I thought I would take a second and post how you can create your own Extension Method. An extension method is a specially defined method that acts like a method defined on a type. LINQ operators, like from, where, select, etc are implemented using extension methods. For example, the where clause checks for a Boolean result of a test (ex: City==”London”).

Creating your first extension method

To show this in action, I want to create my own custom extension method. While the method itself may not be incredibly useful, it should hopefully serve as a simple example of how an extension method works.

Assignment

Create an extension method to write values out of an IEnumerable type to the console window, or better stated in MasterCard commercial style: Not ever having to write a foreach loop to write something out to the console, priceless.

First, let’s look at a simple LINQ query:

string[] aBunchOfWords = {“One”,“Two”, “Hello”, “World”, “Four”, “Five”};

var result =

from s in aBunchOfWords

where s.Length == 5

select s;

Given this query, I can write the values out to the console window using the following:

foreach (var s in result)

{

Console.WriteLine(s);

}

This prints out:

Hello

World

Defining my extension method

Below is an extension method with no return type named Write(). The only difference between an extension method and a normal method is the keyword this defined in the first parameter. this is basically a pointer to the object that had the method invoked. Note that extension methods must be static.

public static class Utils

{

public static void Write(this IEnumerable source)

{

foreach (var item in source)

{

Console.WriteLine(item);

}

}

Using my previous example, I can now use my custom Write extension method as shown below:

result.Write();

Like regular methods, extension methods can also be overloaded. For example, you can create an overload for the Write method that works on IEnumerable (non-generic) source as shown below.

public static void Write(this IEnumerable source)

{

foreach (var item in source)

{

Console.WriteLine(item);

}

}

Like before, we use the this keyword in the method signature

//Fx 1.1 collection

ArrayList ar = new ArrayList();

ar.Add(1);

ar.Add(2);

ar.Add(3);

//calls my custom extension method

ar.Write();

Result:

1

2

3

ObjectDumper

The LINQ Project Tech Preview download also includes a great source code sample called ObjectDumper found at: C:\Program Files\LINQ Preview\Samples\ObjectDumper

ObjectDumper is a class library that let’s you pass an object and, using reflection, it will write the elements and fields of the object to the Console Window, including hierarchical data.

In this case, I’m going to write another ExtensionMethod that calls ObjectDumper so that I can easily call ObjectDumper on any type using the convenient method call notation.

public static class Utils

{

public static void Write(this object source)

{

ObjectDumper.Write(source);

}

public static void Write(this object source, int depth)

{

ObjectDumper.Write(source, depth);

}

}

Here’s what it would look like on the sample I blogged about earlier on why “var” exists:

var result = from s in aBunchOfWords where s.Length == 5 //Creates a new anonymous type with name/value pairs select** new {Value=s, Length=s.Length, FirstThreeLetters=s.Substring(0,3)}**;

Result

Value=Hello Length=5 FirstThreeLetters=Hel

Value=World Length=5 FirstThreeLetters=Wor

Printing manually

//Print values foreach (var x in result) Console.WriteLine(“Value={0}\t Length={1}\t FirstThreeLetter={2}", x.Value, x.Length, x.FirstThreeLetters);

Printing with my custom extension method

//Print values result.ObjectDump();

Language Feature Abuse

While extension methods are handy, they can, like other language features be abused. As LINQ becomes more stable, we’re going to need some clear guidance on when and where to use features. We’re at the earliest stage in development, so we don’t have these now, but you can certainly imagine updating class library design guidelines.

LINQ

Sun and Google announce Web Office *Or not*

LINQ: What is the purpose of var?