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