Thursday, August 09, 2007

C# 3.0 - Extension Methods

Think of extension methods as normal static utility methods you can add to any object.

Extension Methods can be defined in any class. There are only two things you need to do to define an EM. First the method must be public static in a static class, and you must add this to any parameters.

Example
public static class MyExtensions
{
   public static string AddNewLine( this string s )
   {
      return s += "\r\n";
   }
}

Usage

string s = "This is my Test";
Console.Write(s.AddNewLine());
Console.Write("I'm now on a new line");
Console.ReadLine();

This is a fairly trivial example, but I'm sure you are starting to see the power of extension methods.

In C# 2.0 days the above would be:

string s = "This is my Test";
Console.Write(MyExtensions.AddNewLine(s));
Console.Write("I'm now on a new line");
Console.ReadLine();

To my mind, the above is not as readible, but also you have to remember which utility class you put AddNewLine in, or more importantly another coder has to know which class you put the method in.

Microsoft suggest you should use your own Extension Methods sparingly and warns not to extend existing types that you don't control. This is because changes in the existing type could break your code.

I guess this is all logical stuff. I think that most people will use Extension Methods for adding utility functions to standard types, for example the one I can think of, off the top of my head would be something like ToInt() to convert a string to an Int.

2 comments:

Eschaton said...

Objective-C has had "categories" which let you add both instance and class methods to arbitrary classes for something like 15+ years. For example, I can write this code:

@interface NSString (MyCategory)
- (NSString *)stringByAppendingNewline;
@end

@implementation NSString (MyCategory)
- (NSString *)stringByAppendingNewline {
return [self stringByAppendingString:@"\n"];
}
@end

With this in my application, every instance of NSString in it will respond to the -stringByAppendingNewline method, equivalent to your C# 3.0 example. But to gloat, my example would have also worked on OPENSTEP in 1994. (On the other hand, in my example I'd put the @interface section in a header file, which C# doesn't need...)

I suspect that if you take Mac OS X development with Cocoa and Objective-C for a spin, you'll really enjoy it. There are a lot of language and environment features like this that are just taken for granted in Mac OS X development. For example, Tiger and later support NSPredicate strings which are used similarly to LINQ; they're also based on similar work (EOQualifier) done at NeXT in the early-mid 1990s. (By Jack Greenfield, now of Microsoft and Software Factories fame, no less.)

I can understand if you want to wait for Leopard though before really diving in - what's coming in Leopard is really slick. But it all builds on what came before, so anything you learn pre-Leopard won't require all that much un-learning.

KiwiBastard said...

I am actually playing with Objective-C at the moment.

I do like it actually, but unfortunately as a contractor there isn't enough work to justify my time at the moment, but I will continue to look at the hobbyist level