Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

A Use for Extension Methods

Recently over on the alt.net list there has been alot (read: way too much) talk about extension methods. The running consensus seems to be that extension methods are great for extending someone else’s API but have no place in code that you control.

This view point of many was expressed well by Peter Richie as

I see no need to release a framework that includes extension methods for classes, public or not.  Releasing updates to a framework that include extension methods for classes is a different story.  The ability to maintain an established level of quality on existing binaries while still offering the ability to add behaviour to the classes in those binaries is very compelling.  But, I agree with Chad that they be avoided on classes whenever possible.  With .NET 3.5 you have to reference new assemblies to bring in extension methods, they don’t magically appear in the existing assemblies.

and Chad Myers as

I know I’m doom and gloom, but it seems that ext methods should be avoided where ever possible and treated as smells when unavoidable. They’re great in Linq, so the smell is justified, but beware of patchwork ext method frameworks.

I hope to show some code that benefits from extension methods even on classes that I completely control.

Fluent Interfaces

Now I am sure you are thinking “Hey he is going to show how to use native types and extension methods”. I won’t do this, I think enough people already have and it wouldn’t serve my case well for using extension methods on classes that I control.

I like fluent interfaces, especially for value objects. I have used a builder pattern for some time to create these. If people want I can put up a post explaining more on the relationship between value objects and builders but here is some quick example code.

public struct CostBuilder

{

    private readonly int Shares;

    private readonly Money Price;

 

    public CostBuilder Bought(int _Shares)

    {

        return new CostBuilder(_Shares, this.Price);

    }

 

    public CostBuilder Sold(int _Shares)

    {

        decimal alteredprice = this.Price;

        if (alteredprice > 0)

        {

            alteredprice = 0 – alteredprice;

        }

        return new CostBuilder(-_Shares, alteredprice);

    }

 

    public CostBuilder For(Money _Price)

    {

        if (this.Shares > 0)

        {

            return new CostBuilder(this.Shares, _Price);

        }

        else

        {

            return new CostBuilder(this.Shares, 0 – _Price);

        }

    }

 

    public CostBuilder(int _Shares, Money _Price)

    {

        this.Shares = _Shares;

        this.Price = _Price;

    }

 

    public static implicit operator Cost(CostBuilder Builder)

    {

        return new Cost(Builder.Shares, Builder.Price);

    }

}

 

Listing 1: A simple Builder

 

Aaron over at Elutian wrote a post Fluent Fixtures which uses a similar pattern (it is in general similar to the builder pattern). We would then take our builder and put a static instance onto a class named New like this…

static class New

{

    public static CostBuilder Cost;

}

Listing 2: New class which holds builder

 

Finally we can use the above example in a manner similar to

Cost Purchased = New.Cost.Bought(100).For(

    New.Money.InCanada(20000)

);

Listing 3: Using code

 

Now enough about the how to and back to the point of the post Extension Methods… As said earlier we could make this interface nicer possibly by decorating native types with extension methods but the challenge is to show a case where we control the class and we receive benefit from using extension methods.

We have a problem here productivity wise, every item we do this with lives on the New class. In a large domain this quickly adds up. The easy answer is to start putting New classes into various namespaces. Let me just say that this is not only bad but its really annoying. Enter Extension Methods

Context Sensitivity

Extension methods allow me to only have a method visible if you are currently referencing my namespace. This can be used to tweak intellisense a bit so I can only show you what is relevant in your current context when you view the New class unfortunately static methods aren’t supported but we can get around that using a static instance.

public class Builder

{

}

 

public class Create

{

    public static Builder New = new Builder();

}

Listing 4: Create and Builder

 

Now that I have these I can decorate the Builder with extension methods like:

public static CostBuilder Cost(this Builder s)

{

    return new CostBuilder();

}

Listing 5: Extension Method for Builder

 

Now when I go to use it, Create.New will ONLY show me the Cost() method if Cost is in my currently referenced namespaces (as opposed to showing me every object I could every construct). I can do this with all of my objects (I would imagine in a big domain or a generic domain of value objects you may have hundreds of these).

This makes my finding of these builders more efficient as it will automatically ignore the ones that have no place in my current context.

Other Uses

There are lots of things that could use a similar pattern to this. I am simply using it to provide me context sensitive information that I would not otherwise see in a static state. Others that come to mind might be.

IMyService Service = Instance.For.IMyService().WithContext(Context);

or to layer something like this over an IOC container so I only see the interfaces that are currently in my context listed as available options.

ISomeService MyService = Container.For.ISomeService;

 

Is this good? I’m not sure but the ability to use things in a context sensitive fashion like this certainly seems to offer some interesting possibilities. I can come up with lots of fun ways of abusing using this :)

This entry was posted in DDD, Featured, Fluent Interface. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

9 Responses to A Use for Extension Methods

  1. Pingback: How does Greg Young's Fluent Interface work? | BlogoSfera

  2. John Chapman says:

    Greg,

    I think I’m finally converted for real this time. I think I found where I enjoy extension methods the most even when you control both the consumer class and the target class. I think it works great for separation of concerns regarding business objects and UI. For example why add methods like GetFullName() to your person class when it is display specific, why not add it via extension methods to your UI layer?

    I wrote more about this on my blog:
    http://jaychapman.blogspot.com/2007/12/ui-good-use-for-extension-methods.html

  3. John Chapman says:

    Greg,

    I’m one of those people that have put extension methods down pretty hard. You’re actually helping me keep a somewhat open mind on the subject. Thanks to your post I think I’m going to try and reserve further judgment for about a year to see how developers find uses for extension methods.

    http://jaychapman.blogspot.com/2007/12/reserving-judgment.html

  4. I have an extension method for firing/raising events that I like, you can see it here:

    http://elegantcode.com/2007/12/05/firing-events-with-extension-methods/

    It reduces firing an event from:
    if (OnMyEvent != null)
    OnMyEvent(this, myArgs);

    to
    OnMyEvent.Fire(this, myArgs);

  5. Mike Breen says:

    > If people want I can put up a post explaining more on the relationship between value objects and builders

    I’d like to see this. Thank you.

  6. KG2V says:

    One of the BEST uses I’ve seen so far – I’m in the middle of an upgrade/refactor of an old project. Part of it involves getting rid of an old cutom control

    I’ve added an extention method to mimic the syntax/functionality of the new control – so now I can change the code talking to the old control slowly to the new syntax, and when the time comes – poof – I’m done. (yeah – we need to break the fact that when it was coded back 7 years ago, there is very little seperation of concerns between the UI and the rest of the app

  7. I think there’s lots of uses for extension methods. None that really don’t compromise at least one programming principle; except maybe behaviour for interfaces. Adding behaviour to interfaces assumes you’re code is at lease slightly interface-oriented; but allows you to polymorphicly add behaviour to your interfaces.

    The builder use for extension methods is an excellent way to keep concerns separate. If you’re not even slightly aspect-oriented, though, you might not care. If you’re classically object-oriented, you might have a problem with this.

    Language-oriented programmers might use extension methods to “rename” all framework methods to something in their ubiquitous language. I don’t know if I agree with this; at some point you have to accept the framework you’re using.

  8. Hey Greg,

    This pattern lends itself very well to use extension methods nicely – I can for instance think of Visual Studio project templates taking advantage of this too. Creating a certain kind of project will add references to the extension assemblies that contain the methods I might find useful in this project.

    I think the fear of Extension methods are slightly overrated. Yes, they can be used in very bad ways, similar to many other things that we’ve been using for years ;o)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>