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.On This Page