Be Careful With the var Keyword and Expression Builders
March 21, 2009I 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.
If you and your team want to learn more about how to write maintainable unit tests and get the most out of TDD practices, make sure to have look at our trainings and workshops or check out the books section. Feel free to reach out at info. @ principal-it .be
Jan Van Ryswyck
Thank you for visiting my blog. I’m a professional software developer since Y2K. A blogger since Y2K+5. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Past organizer of the European Virtual ALT.NET meetings. Thinking and learning about all kinds of technologies since forever.
Comments
Writing Maintainable
Unit Tests
Watch The Videos
Latest articles
-
Contract Tests - Parameterised Test Cases
June 28, 2023
-
Contract Tests - Abstract Test Cases
April 12, 2023
-
Contract Tests
February 1, 2023
-
The Testing Quadrant
June 15, 2022
-
Tales Of TDD: The Big Refactoring
February 2, 2022
Tags
- .NET
- ALT.NET
- ASP.NET
- Agile
- Announcement
- Architecture
- Behavior-Driven Development
- C++
- CQRS
- Clojure
- CoffeeScript
- Community
- Concurrent Programming
- Conferences
- Continuous Integration
- Core Skills
- CouchDB
- Database
- Design Patterns
- Domain-Driven Design
- Event Sourcing
- F#
- Fluent Interfaces
- Functional Programming
- Hacking
- Humor
- Java
- JavaScript
- Linux
- Microsoft
- NHibernate
- NoSQL
- Node.js
- Object-Relational Mapping
- Open Source
- Reading
- Ruby
- Software Design
- SourceControl
- Test-Driven Development
- Testing
- Tools
- Visual Studio
- Web
- Windows
Disclaimer
The opinions expressed on this blog are my own personal opinions. These do NOT represent anyone else’s view on the world in any way whatsoever.
About
Thank you for visiting my website. I’m a professional software developer since Y2K. A blogger since Y2K+5. Author of Writing Maintainable Unit Tests. Provider of training and coaching in XP practices. Curator of the Awesome Talks list. Thinking and learning about all kinds of technologies since forever.
Latest articles
Contract Tests - Parameterised Test Cases
Contract Tests - Abstract Test Cases
Contract Tests
The Testing Quadrant
Contact information
(+32) 496 38 00 82
info @ principal-it .be