web-dev-qa-db-fra.com

Constructeur surchargeant ou autorise NULL?

Quelle est la conception préférée à utiliser, un constructeur qui permet à NULL ou à deux constructeurs où l'on jette un ArgumentNullException sur NULL?

Deux constructeurs avec lancement d'exception

public class Foo
{
    private IDictionary<string, string> _bar;

    public Foo()
    {
        _bar = new Dictionary<string, string>();
    }

    public Foo(IDictionary<string, string> bar)
    {
        if (bar == null) { throw new ArgumentNullException(); }
        _bar = bar;
    }
}

Un constructeur qui gère NULL

public class Foo
{
    private IDictionary<string, string> _bar;

    public Foo(IDictionary<string, string> bar = null)
    {
        if (bar == null) {
            _bar = new Dictionary<string, string>();
        } else {
            _bar = bar;
        }
    }
}
3
Fred

Bien que l'utilisation de null pour indiquer une valeur par défaut est une principale principale bien établie qui redevient aux racines C/C++ de C #, une autre approche pourrait être d'emprunter les concepts du Option Type (appelé Maybe in haskell)

Cela obligera l'appelant à préciser explicitement s'il veut souhaiter la valeur par défaut ou non. Cela évite la confusion sur le passage délibérément null comme un mauvais paramètre et en utilisant null pour indiquer facultatif:

Vous auriez alors un constructeur unique qui couvre à la fois les préoccupations de votre code "deux constructeurs".

public Foo(Option<IDictionary<string, string>> optionalBar)
{
    if (bar == null) 
       throw ArgumentNullException();
    if (bar.HasValue) {
        _bar = new Dictionary<string, string>();
    } else {
        _bar = bar.Value;
    }
}

Malheureusement, c # ne coule pas assez bien que de dire A FP Language, qui utiliserait le motif correspondant à la raison de Some<Dictionary> et None.

0
StuartLC

Je suis pour le premier cas.

Dans le second cas, il favorise null comme paramètre valide. IMO null ne doit pas être utilisé pour indiquer l'absence de valeur. C'est pourquoi Option types existe (comme indiqué par StuartLC).

0
Euphoric

Je ne suis pas extrêmement époustouflé par soit pour être honnête.

Le premier peut lancer une exception inattendue et la seconde initiale une variable de membre qui n'a même pas été fournie sous forme de paramètre. Les constructeurs ne doivent pas générer de comportement inattendu.

Je préférerais quelque chose comme ça:

public class Foo
{
    private IDictionary<string, string> _bar;

    private IDictionary<string, string> Bar
    {
        get
        {
            if (_bar == null)
                _bar = new Dictionary<string, string>();

            return _bar;
        }

        set { _bar = value; }

    }

    public Foo()
    {

    }

    public Foo(IDictionary<string, string> bar)
    {
        Bar = bar;
    }
}

L'utilisateur est libre de fournir un paramètre ou d'appeler le constructeur sans paramètre. Et si, par une supervision, la propriété est appelée sans être initialisée, elle crée une sur la mouche via une instanciation paresseuse.

0
Robbie Dee