Soyons claires, le titre ne reflète pas mon avis, ni même le contenu de cet article. Il ne sert qu’à attirer le chaland sur un contenu « coup de gueule ».

Depuis que je fais du .net, j’en vois et j’en entends des vertes et des pas mures sur .net et ses problèmes de performances. Dernièrement (hors contexte professionnel heureusement), j’ai été assez choqué par une situation qui ne se généralise peut-être pas encore, mais qui prend tout de même de l’ampleur : « n’utiliser que le constructeur par défaut d’une classe ».

Le framework fourmille de classes disposant de x constructeurs. Ceux-ci ne sont pas là juste pour faire beau dans le décor. Ils sont souvent destinés à une instanciation optimale.

Oui, dit comme cela, mes propos peuvent sembler étranges, et un peu old school ou totalement has been…

Cependant, quand je vois un modèle qui implémente INotifyProprtyChanged et que tout le monde utilise les accesseurs pour définir les propriétés de l’instance fraichement crée, ça me fou en rogne. Avec XAML, il ne faut donc pas s’étonner d’avoir des problèmes de performances.

Prenons une classe sans constructeurs (comme j’en vois trop) :

public class Item1 : NotifyPropertyChangedBase
{
    private Guid _id; 
    private Boolean _isRead;
    private Boolean _isStarred;

    public string Id
    {
        get { return _id; }
        set
        {
            if (_id == value) return;
            _id = value;
            RaisePropertyChanged();
        }
    }

    public Boolean IsRead
    {
        get { return _isRead; }
        set
        {
            if (_isRead == value) return;
            _isRead = value;
            RaisePropertyChanged();
        }
    }

    public Boolean IsStarred
    {
        get { return _isStarred; }
        set
        {
            if (_isStarred == value) return;
            _isStarred = value;
            RaisePropertyChanged();
        }
    }
}

Prenons une seconde classe similaire avec constructeurs :

public class Item2 : NotifyPropertyChangedBase
{
    private readonly Guid _id; 
    private Boolean _isRead;
    private Boolean _isStarred;

    public Item2() : this(Guid.NewGuid(), false, false) { }
    public Item2(Guid id) : this(id, false, false) { }

    public Item2(Guid id, bool isRead, bool isStarred)
    {
        _id = id;
        _isRead = isRead;
        _isStarred = isStarred;
    }

    public Guid Id
    {
        get { return _id; }
    }

    public Boolean IsRead
    {
        get { return _isRead; }
        set
        {
            if (_isRead == value) return;
            _isRead = value;
            RaisePropertyChanged();
        }
    }

    public Boolean IsStarred
    {
        get { return _isStarred; }
        set
        {
            if (_isStarred == value) return;
            _isStarred = value;
            RaisePropertyChanged();
        }
    }
}

L’instanciation de chacune avec les mêmes valeurs donnera ceci :

var i = new Item1{Id = id,IsRead = true, IsStarred=true};
var j = new Item2(id, true,true);

Rien de bien choquant. Si ce n’est qu’en instanciant la première classe, cela revient à écrire le code suivant :

public Item1(Guid id, bool isRead, bool isStarred)
{
    if (_id != id)
    {
        _id = id;
        RaisePropertyChanged();
    }
    if (_isRead != isRead) 
    {
        _isRead = isRead;
        RaisePropertyChanged();
    }
    if (isStarred != isStarred)
    {
        isStarred = isStarred;
        RaisePropertyChanged();
    }
}

Honnêtement, iriez-vous volontairement écrire ceci ?