21 Mar
2009

Be Careful With the var Keyword and Expression Builders

Category:UncategorizedTag: :

I just want to point out a small tidbit I ran into earlier this week. I was using the following simplified expression builder that provides a fluent interface for creating an instance of a Product.

public class Product
{
    public Double Price { get; private set; }
    public String Name { get; private set; }
    public String Manufacturer { get; private set; }

    public Product(String name, String manufacturer,
                   Double price)
    {
        Price = price;
        Name = name;
        Manufacturer = manufacturer;
    }
}

public class ProductBuilder
{
    private String Manufacturer { get; set; }
    private String Name { get; set; }
    private Double Price { get; set; }

    public static ProductBuilder CreateProduct()
    {
        return new ProductBuilder();
    }

    public ProductBuilder Named(String name)
    {
        Name = name;
        return this;
    }

    public ProductBuilder ManufacturedBy(
        String manufacturer)
    {
        Manufacturer = manufacturer;
        return this;
    }

    public ProductBuilder Priced(Double price)
    {
       Price = price;
        return this;
    }

    public static implicit operator Product(
        ProductBuilder builder)
    {
        return builder.Build();
    }

    private Product Build()
    {
        return new Product(Name, Manufacturer, Price);
    }
}

The following code is an example of how to use this expression builder.

var product = ProductBuilder
    .CreateProduct()
    .Named("iPod Touch")
    .ManufacturedBy("Apple")
    .Priced(273);

There is one minor inconvenience with this code. One may think that the product variable contains an instance of a Product. Unfortunately, this is not the case. The product variable however contains an instance of ProductBuilder and not an instance of Product because the implicit cast operator is never called. How would the compiler know that you want to keep a reference to Product and not a ProductBuilder? Bringing in a bit more ceremony makes this code more easier to comprehend without side effects.

Product product = ProductBuilder
    .CreateProduct()
    .Named("iPod Touch")
    .ManufacturedBy("Apple")
    .Priced(273);

A small price to pay for better readability. On the other hand, you will never encounter this when you pass in the Product to another method.

var product = ProductBuilder
    .CreateProduct()
    .Named("iPod Touch")
    .ManufacturedBy("Apple")
    .Priced(273);

DoSomethingWith(product);

public void DoSomethingWith(Product product)
{
    // ...
}

In this case the implicit cast operator does get called when passing the ProductBuilder instance to the DoSomethingWith method. If lazy initialization is what you want, then the var keyword is the perfect match for this.

var product = ProductBuilder
    .CreateProduct()
    .Named("iPod Touch");

// Do something else
product.ManufacturedBy("Apple")
    .Priced(273);

This may all be straightforward stuff, but I noticed that it kept bugging me every time I didn’t paid attention.

5 thoughts on “Be Careful With the var Keyword and Expression Builders

  1. Hmm, the code provided makes perfect sense to me. I can’t see how in the initial “expression builder” statement would ever assume that you were looking for an instance of the Product class. There may be an implicit operator to cast a ProductBuilder as a Product, but the compiler can’t assume that’s what you’re trying to do. The implicit operator means that you can cast a ProductBuilder to a Product, but not that you must. The var keyword gets a type for that statement, and no more. Now, if your first var statement ended with a call to Build() (which might as well be public, given the implicit cast) then the var would easily know it should be a Product and not a ProductBuilder.

    Also, be careful with the use of the term “Expression Builder” when referring to .NET 3.0, especially when referring to the keyword “var”. I was hoping to see some LINQ code in here or the building of an Expression tree, like Charlie describes here: http://blogs.msdn.com/charlie/archive/2008/01/31/expression-tree-basics.aspx

Comments are closed.