DevTalk.net

ActiveMesa's software development blog. MathSharp, R2P, X2C and more!

Extension Method Patterns

with 8 comments

In almost every application I work with somebody – either me or another developer – uses extension methods to add what they believe to be ‘missing’ functionality to classes. Having seen a huge number of examples, I’ve began to realize that there are, in fact, implementation patterns related to extension method usage. In other words, there are typical problems that extension methods are used to solve. This article is an overview of these problems.

Composite Extension Method

This type of method is created when you need to call two (or more) methods together, and you want to simplify the call. There’s a myriad of situations where this is needed – for example, the StringBuilder class has an AppendFormat() and an AppendLine(), but what if you want to output a formatted string with a line break? A composite extension method helps you do just that.

public static StringBuilder AppendFormatLine(
  this StringBuilder sb, string format, params object[] args)
{
  return sb.AppendFormat(format, args).AppendLine();
}

In actual fact, there are many use-cases for method combinations, but they typical one is sequential call (i.e., call A() then B()).

Recursive Extension Method

This type of method helps you avoid recursive calls by wrapping the ‘folding’ into an extension method. For example, the Path.Combine() method takes only two parameters, which isn’t very convenient if you have more than two elements in a path.

// we have to write this
Path.Combine(a, Path.Combine(b, c));
// but we _want_ to write this
new[]{a, b, c}.PathCombine();

Params Extension Method

Since in .Net T[] is not equivalent to params T[], we can’t simply make a bunch of T arguments and pass them arbitrarily to a method that takes an array. The solution here is to create extenion methods which take a params array and proxy the calls then and there. For example, we can define the following:

public static void AddRange<T>(this IList<T> list, params T[] objects)
{
  foreach (T obj in objects)
    list.Add(obj);
}

And here’s how one would use it:

var list = new List<int>();
// previously, you would have to write this
list.AddRange(new[] {1, 2, 3});
// but now you can write this
list.AddRange(1, 2, 3);

Anti-static Extension Method

Instead of calling a static method of class X, we instead call an extension method on this class (if this is possible, that is). The classical example to this approach is the way String.Format() gets turned into an extension method:

public static string ƒ(this string format, params object[] args)
{
  return string.Format(format, args);
}

Are you spooked by the curly f?

Factory Extension Method

These methods let you completely bypass the object constructor, hiding it behind more concise, intention-revealing methods. One popular example is the creation of a date from a fluent expression so that one can write 19.June(1986). Note that the name of the method itself is an implicit parameter used for the creation of the DateTime structure:

public static DateTime June(this int day, int year)
{
  return new DateTime(year, 6, day);
}

The factory method is not obliged to attach this method to the first parameter’s type. For example, if your goal is the creation of an object (say, from a line of Xml) from a key-value structure, you can pass the whle object. We just need to remind ourselves that C# supports anonymous types. Then, the creation of an arbitrary piece of Xml can look like this:

new { Name="Dmitri", Age=25}.ToXElements();
// will give us <Name>Dmitri</Name> and <Age>25</Age>

I won’t show the implementation of this method here – you can find it in MiscUtil – but I hope this is a good reminder to our readers that an anonymous class is de facto a key-value collection. And hey – Asp.Net MVC happily exploits this language feature.

Monadic Extension Method

Monadic extension methods let you implement what I call monadic syntax. My previous article shows fairly clear examples of what this is and what it’s for, but I’ll mention it here too for posterity – here’s an extension method that allows chain calls that only ‘happen’ if the argument is non-null:

public static TResult With<TInput, TResult>(
  this TInput o, Func<TInput, TResult> evaluator)
  where TResult : class where TInput : class
{
  if (o == null) return null;
  return evaluator(o);
}

I’d like to point out here that monadic extension methods are typically useful in domain areas where F# is more useful than C#. And, as you may remember, F# has not just extension methods but also extension properties, which adds an extra aspect usability-wise… but at the expense of all the headaches you’ll get related to immutability and other capricious behavior.

Proxy Extension Method

Sometimes, in order to create a fully-fledged fluent interface, it’s useful to keep some state associated with an object. Since in the conditions of staticity (everything is static) persistence is very difficult, we use a proxy object which can act as some sort of configurator or ‘smart parameter’ for something else. Besides that, it can implement a host of methods, which will not pollute the global scope were they extensions over object.

Here’s an exampe – SomeProxy<T> which acts as a convertible wrapper for T:

public class SomeProxy<T>
{
  private readonly T subject;
  private object something;
  internal SomeProxy(T subject, object something)
  {
    this.subject = subject;
    this.something = something;
  }
  public static implicit operator T(SomeProxy<T> obj)
  {
    return obj.subject;
  }
  // other useful operators here
}

This class can then be ‘substituted’ in lieu of the original object with an extension method:

public static SomeProxy<T> Configure<T>(this T subject, object something)
{
  return new SomeProxy<T>(subject, something);
}

Unfortunately, you won’t be able to ‘layer’ these mixin-like constructs over one another without having to perform casts.

Functionality Extension Method

This is the catch-all type for any type of extension method. A typical example is the (yet missing) ForEach() method for Linq, which Eric Lippert blogged about. It’s an interesting read – mainly concerned with immutability that everyone seems to be obsessing over these days.

The internet is positively teeming with various mini-libraries of functionality extension methods – not just ForEach(), but also really bizarre constructs that are often, upon close ovservation, very obscure. For example, the Step() method which is simply a for-loop replacement. You would use it like this:

// all numbers from 5 to 9 with a step of 2 are written to the console
5.Step (9, 2, i => Console.WriteLine (i));

Conclusion

I’m not sure if it’s fully valid to speak of ‘extension method patterns’ in the same architectural sense as, say, GoF design patterns, but… it’s something that caught my eye, and I guess putting it down on paper (so to speak) helps me better spot and classify these when I see them.

Written by Dmitri Nesteruk

September 30th, 2010 at 4:14 pm

Posted in CSharp

  • http://vtimashkov.tumblr.com vtimashkov

    Great post! Thank you, Dmitri!
    1. for me, this post could be a great inspiration for you previous post about desired features in C# 5. Practically each point in this post could be a new (and quite good) option in C# 5.
    2. there is a small problem – in Firefox, code snippets are arounded with tags like .

    • http://devtalk.net Dmitri Nesteruk

      Thanks for the pointer regarding code snippets – I did mess up on this one. And I think the C#5 post just went platinum :)

  • http://purs.wordpress.com/ Dmitry

    Very nice article! But still, i prefer to use extension methods just in situations, where they improve readability and as seldom as i can..

  • http://twitter.com/0x39DC 0x39DC

    Very nice article. But, for example, i prefer to use extension methods just to improve readability and as seldom as i can.

  • Maxim

    Thanks, Dmitri. It’s always pleasant to read your posts. A lot of helpful information.

  • Andrew

    Great artical Dmitry ! Thanks.

    I liked example from “Params Extension Method” section especially. It’s Very easy and elegant solution.

    I remember that in one of your podcasts you discused one usefull (as i think) usecase of Extension methods. Anton Onikiychuk told how Extension methods allow to do more tiny and elegant interfaces. And you know I tried it in one of my project and i should say It’s really good solution :)

    • Anonymous

      Well, I’m glad you like it! Extension methods really do make life better in a variety of applicable domains. I only hope that C#5 will bless us with extension properties just like F# does. Now that would be even more fun!

  • Pingback: خواندنی های 12 مهر و چند روز قبل | alisite