Functional Inspiration – Revisiting the With extension method

Return to the very first post for improvement

This is the fourth entry of a blog series about how functional programming, and the F# training I recently went to, gives me inspiration in my day-to-day work in C#. It is going to propose an other implementation of the “With” method, which this time deals with immutable data structures.

No long explanation today, here is a very simple immutable class representing the same Person as in the first post :

public class Person
{
    public readonly string Name;
    public readonly string Town;
    public readonly string Country;
    public readonly int Age;

    public Person(string name, string town,
                    string country, int age)
    {
        this.Name = name;
        this.Town = town;
        this.Country = country;
        this.Age = age;
    }
}

We can this time see that all the fields are defined “readonly”, making that data structure immutable. As the value of the fields can only be modified inside the constructor, we will not be able to use a delegate parameter as previously. We will have to find a way to modify the values in the constructor.

To do so, we define a second (private) constructor. Surprise ! The Irrelevantable construct shows up :

private Person(
    Person source,
    Irrelevantable<string> name,
    Irrelevantable<string> town,
    Irrelevantable<string> country,
    Irrelevantable<int> age)
{
    this.Name = name.IsRelevant ? name.Value : source.Name;
    this.Town = town.IsRelevant ? town.Value : source.Town;
    this.Country = country.IsRelevant ? country.Value
                                        : source.Country;
    this.Age = age.IsRelevant ? age.Value : source.Age;
}

When this constructor is called, it populates the properties using either the source Person’s properties, either the following arguments, depending on whether they are “relevant”. If this constructor is called with a single “relevant” value, it acts quite as out original “With” method.

And using the C#4.0 default values capabilities, we can make things even better :

public Person With(
    Irrelevantable<string> name
        = default(Irrelevantable<string>),
    Irrelevantable<string> town
        = default(Irrelevantable<string>),
    Irrelevantable<string> country
        = default(Irrelevantable<string>),
    Irrelevantable<int> age
        = default(Irrelevantable<int>))
{
    return new Person(
        this,
        name: name,
        town: town,
        country: country,
        age: age);
}

This public “With” method defines default values for all properties, allowing us to give only the values of the properties that we want to change.

Person someone = new Person(
    name: "Luc",
    town: "Paris",
    country: "France",
    age: 29);

Person someoneElse = someone.With(age: 30);
Person someAmerican = someone.With(
                            name: "Luke",
                            country: "United States");

You can notice here that this time the syntax allows us to define multiple changes in a concise form, and works nicely with immutable data structures !

This entry was posted in Functional Inspiration and tagged , . Bookmark the permalink.

Comments are closed.