Last week I discovered a rather wonderful construct for objects with long constructors, e.g. immutable value types:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class UserProfile { public string City { get ; protected set ; } public string Country { get ; protected set ; } public Uri Url { get ; protected set ; } public string Email { get ; protected set ; } public string Tagline { get ; protected set ; } public UserProfile( string city, string country, Uri url, string email, string tagline) { ... } } |
This constructor has bad Connascence of Position (CoP); to construct a UserProfile instance, users have to know the position of each parameter. Otherwise they might mix up the city with the country for example:
1 2 3 |
// Spot the bug! var profile = new UserProfile( "NZ" , "Wellington" , |
This won’t be a problem with named parameters in C# 4.0, but until then, a nice alternative is a fluent builder class as described:
1 2 3 4 5 6 |
UserProfile profile = new UserProfileBuilder() .WithCity( "Wellington" ) .WithCountry( "NZ" ) .WithUrl( new Uri( "https://richarddingwall.name" )) .WithEmail( "rdingwall@gmail.com" ) .WithTagline( ".NET guy" ); |
Builders are very easy to implement. Each With method records its value and returns the current builder instance. Then we provide an implicit cast operator that finally constructs a UserProfile with all the parameters in the right places.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class UserProfileBuilder { internal string City { get ; set ; } internal string Country { get ; set ; } // ... etc public UserProfileBuilder WithCity( string city) { this .City = city; return this ; } // ... etc public static implicit operator UserProfile(UserProfileBuilder builder) { return new UserProfile(builder.City, builder.Country, builder.Url, builder.Email, builder.Tagline); } } |
I really like this!