Builder pattern implicit conversions

Leveraging implicit conversions to make using the builder pattern easier

Home DailyDrop

Daily Knowledge Drop

Usually when using the builder pattern, a final Build method (or similarly named method) is invoked to generate the final entity from the builder entity. Using an implicit operator, this final step can be removed, and the final entity can automatically be generated from the builder entity.


Examples

In these examples, there is a simple Order entity:

public record Order(int Id, int lineItemCount, double Total);

There is also an OrderBuilder class, which is used to build an Order:

public class OrderBuilder
{
    // store some order information
    private int _id;
    private int _lineItemCount;
    private double _total;

    // method to give an order an id
    public OrderBuilder WithId(int Id)
    {
        _id = Id;
        return this;
    }

    // add a simple line item to the order
    public OrderBuilder WithLineItem(double lineItemAmount)
    {
        _lineItemCount++;
        _total += lineItemAmount;

        return this;
    }

    // create an Order from the OrderBuilder information
    public Order Build()
    {
        return new Order(_id, _lineItemCount, _total);
    }
}

Build method

Usage of the above builder is easy:

var order = new OrderBuilder()
    .WithId(100) // give the order an id
    .WithLineItem(99) // add line items
    .WithLineItem(149)
    .Build(); // remember to build!

Console.WriteLine(order);

The above is the typical usage of the builder pattern - building up the entity using various methods, and then at the end calling a Build method to create the final entity (Order in this example) using the information supplied to the builder.

The output of the order:

Order { Id = 100, lineItemCount = 2, Total = 248 }

Nothing inherently wrong or incorrect with this code or approach - however an implicit operator can be added to the OrderBuilder class to make the pattern and classes even easier to use.


Implicit

Adding the following implicit operator to the OrderBuilder class, allows for the Build method to automatically be invoked when converting the OrderBuilder instance to an Order instance:

public static implicit operator Order(OrderBuilder b) => b.Build();

With the above added to the OrderBuilder class, the following is now possible:

// instead of "var", the actual type
// Order is used
Order order = new OrderBuilder()
    .WithId(101)
    .WithLineItem(100)
    .WithLineItem(29);
// No Build required!

Console.WriteLine(order);

With this code snippet, as the OrderBuilder is being converted to Order implicitly, the implicit operator is called which calls the Build method to convert the OrderBuilder to an Order automatically. No need for the Build method to be used!


Notes

This is a small update to the code, but for the developers consuming the classes, the overall developer experience is improved. This gives the developer the flexibility to use the class how they would like - either using the Build method, or doing the implicit conversion.


References

Bonus: Builder Pattern with the implicit operator using c#

Daily Drop 203: 16-11-2022

At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.

The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.
c# .net pattern builder implicit conversion