LINQ: Creating your first Extension Method
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<T>(this IEnumerable<T> 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.
Comments
- Anonymous
October 15, 2005
Nice post Daniel,
I had developed a Business Layer strongly typed on DLinq with Many-to-Many support.
Simple database struct: Users and Groups as like project sample.
http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=109996
Cheers,
Javier Luna - Anonymous
October 23, 2005
Extension methods are extremely useful. The other day while trying to write a method that shows fancy names for enumerated types, I was forced to create an extension method and got a bit mad that they are not there in C#2.0.
See http://blogs.msdn.com/abhinaba/archive/2005/10/21/483337.aspx
However like overloaded operators they get me a bit suspicious and always make me look up the code of the extension method to ensure that they do what I wanted them to do.... - Anonymous
June 09, 2006
I appreciate the author in explaining his views in a very clear and simple example. - Anonymous
August 21, 2006
How can I use ObjectDumper in my code? I tried to use it and get the "the name 'ObjectDumper' doesnot exist in the current context" error. How can I resolve this error?
My email address is maulikk2004@gmail.com