C# 6.0 Features Part II : Primary Constructors

Thursday, August 14, 2014

Primary constructors are a feature you’ll find in a few programming languages, including F#, Scala, and Kotlin. A primary constructor allows us to define a constructor for a type and capture the constructor parameters to use in initialization expressions throughout the rest of the type definition.  Here’s one simple example:

public struct Money(string currency, decimal amount) 
{
    public string Currency { get; } = currency;
    public decimal Amount { get; } = amount;
}

Notice how the primary constructor arguments appear inside parentheses just after the type name. The code can then use the arguments in field initializers and property initializers. Common questions about this new syntax revolve around parameter validation, and how primary constructors can work with other explicit constructors. Here’s another example.

public class AddUserCommand(User newUser, User creator) : Command
{
    public AddUserCommand(User newUser)
        : this(newUser, creator: newUser)
    {
    }

    public User NewUser { get; protected set; } = newUser;
    public User Creator { get; protected set; } = Verify.NotNull("creator", creator);
    Guid _creatorId = creator.Id;
}

Once you have a primary constructor, all other constructors must ultimately call into the primary ctor using this(), which makes sense since we always want the primary constructor arguments to be available for initialization (although a struct will still have a non-replaceable default constructor that will initialize all members to default values).

Validation is a bit trickier, but simple validation checks are possible in the initialization expressions.

I really like the primary constructor syntax for components that are managed by an IoC container. Typically these components have a single constructor to accept dependencies, and they need to store the dependencies in a field or property. Validation of the dependencies is not a concern as most containers will (or can) raise an error if a dependency cannot be found.

public class UserController(IUserStorage storage) : Controller
{
    public ActionResult Index()
    {
         // ...
    }

    IUserStorage _storage = storage;
}

The primary constructor syntax means there is a little less code to write for these types of components.


Comments
gravatar Jesse C. Slicer Thursday, August 14, 2014
One quick thing to note (to further drive home the benefit of this) is that your five-line Money example would have taken at least 11 lines in C# 5. So a savings of over 50% by removing boilerplate!
gravatar Patrick D Sullivan Thursday, August 14, 2014
I like this new syntax. Just making what you were able to do before easier.
gravatar Alexander Batishchev Thursday, August 14, 2014
Why do you need functional-like syntax in C# if you have functional F#? Because F# is OO-like? This can't be a reason! Use C# for OOP and use F# for FP. You don't need to mix them up.
gravatar Alexander Batishchev Thursday, August 14, 2014
If your like this syntax just use F#, this is my point. C# should not and can not be all-in-one-language-for-everything.
gravatar Chris Marisic Tuesday, August 19, 2014
@Alexander I strongly disagree. One language to rule them all. C# all your base belong to us. It just needs to fully absorb F#.
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!