Sehr oft sieht man folgendes Beispiel:
public class StringComparer
{
private CompareInfo m_CompareInfo;
private System.Globalization.CompareOptions m_CompareOptions;
public StringComparer(CultureInfo current)
{
if (current != null)
{
this.m_CompareInfo = current.CompareInfo;
}
else
{
this.m_CompareInfo = CultureInfo.CurrentCulture.CompareInfo;
}
this.m_CompareOptions = System.Globalization.CompareOptions.IgnoreCase;
}
}
Es gibt einen Constructor in dem alles „Verlangt“ wird aber z.b. einige Parameter bei null mit Default Werten gesetzt werden. Was ist daran schlecht? Na ja gehen Sie doch einfach mal davon aus das jemand der diese Klasse benutzt keine Zugang zum Code hat. Wie soll er bitte wissen dass bei Übergabe von Null automatisch eine Default Wert gesetzt wird und nicht eher eine Exception fliegt? Besser ist es einfach einen zweiten Constructor anzubieten der diese Werte einfach nicht benötigt.
public class StringComparer
{
private readonly CompareInfo m_CompareInfo;
private readonly CompareOptions m_CompareOptions;
public StringComparer()
: this(CultureInfo.CurrentCulture, CompareOptions.IgnoreCase)
{ }
public StringComparer(CultureInfo info, CompareOptions options)
{
m_CompareInfo = info.CompareInfo;
m_CompareOptions = options;
}
}
Ein Benutzer kann nur diese Klasse verwenden ohne irgendwelche Parameter anzugeben. Das verhalten bleibt unverändert da wir den „größeren“ Constructor mit Default Werten aufrufen. Zusätzlich hat der Benutzer auch weiterhin die Möglichkeit entsprechende Werte selber zu übergeben. Dadurch haben wir die Versteckte If-Bedingung aufgelöst und somit dem Code lesbarer, verständlicher und wartbarer gemacht. Es ist auch nicht zu empfehlen Fehler vor Benutzer zu verstecken bzw. einfach zu schlucken (Hier ist die If-Bdedingung mit dem Default Wert gemeint), denn falls wirklich Null als Wert gesetzt wird dann ist das ein Fehler der entsprechend auffallen muss. Dies könnte im weiteren Ablauf durch einen NullReferenceExcpetion geschehen oder in dem wir schon im Konstruktor eine ArgumentNullException werfen.
Sehr wichtig ist hier, dass alle „kleineren“ Constructor den „größten“ aufrufen müssen und nur in diesem die entsprechende „Logik“ implementiert ist. Nur so verhindern wir unterschiedliches verhalten bei unterschiedlichen Constructor Aufruf und produzieren keinen duplizierten Code.