Blog Arolla

Inspiration fonctionnelle – Revisitons la méthode With

Retour sur le tout premier billet pour amélioration

Ce billet est le quatrième d’une série sur la façon dont la programmation fonctionnelle, et la formation F# à laquelle j’ai récemment assisté, m’apportent de l’inspiration dans mon travail quotidien en C#. Je vais y proposer une autre implémentation de la méthode “With”, qui fonctionne cette fois ci également pour des structure immuables.

Pas de grande explication aujourd’hui, voici tout d’abord une classe immuable représentant la même Person que dans le premier billet :

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;
    }
}

On peut remarquer que tous les champs sont définis “readonly”, ce qui rend la structure immuable. Etant donné que les valeurs des champs ne peuvent être mises à jour que dans le constructeur, nous ne serons pas en mesure d’utiliser un délégué en paramètre comme c’était le cas précédemment. Nous allons donc avoir à modifier ces valeurs à l’intérieur du constructeur.

Pour ce faire, nous définissions un second constructeur (privé). Surprise ! On utilise la construction Irrelevantable des deux derniers billets :

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;
}

Analysons un peu le fonctionnement de ce constructeur. Quand il est appelé, il remplit les différentes propriétés de la classe en utilisant soit la valeur de la propriété correspondante de l’objet Person passé en paramètre, soit un des arguments suivants, en fonction de s’ils sont “appropriés” ou “sans objet”.

Si le constructeur est appelé sans aucune valeur “appropriée”, il agit donc comme un constructeur de copie. S’il est appelé avec une seule valeur “appropriée”, il se comporte exactement comme la méthode d’extension “With” présentée au départ.

Et grâce à l’utilisation des valeurs par défaut, introduites en C# 4.0, on peut rendre les choses à la fois plus pratiques et élégantes :

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);
}

La méthode publique “With” définit des valeurs par défaut pour toutes les propriétés, nous permettant de ne fournir en paramètre que les valeurs à modifier.

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");

Vous pouvez remarquer ici que la syntaxe nous permet même de définir plusieurs changements de manière très concise ! Et cette fois la méthode fonctionne aussi bien pour des structures muables qu’immuables !

@pirrmann

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *