Seit der Version 4.0 sind in C# Methoden mit Parametern erlaubt, die einen Default-Wert besitzen. Dies kann auch auf Contructor-Methoden angewendet werden, also z.B.
1 2 3 4 5 6 7 8 9 10 11 12
| public class A
{
public A()
{
// ...
}
public A(string x = "default")
{
// ...
}
} |
Die Frage ist nun: Welcher Constructor wird verwendet, wenn ich eine Instanz mit A a = new A();
erzeuge?
Versuch 1
Im oben beschriebenen Fall kann dies schnell beantwortet werden, indem man es einfach ausprobiert:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| namespace ConstructorQuiz1
{
class Program
{
static void Main (string[] args )
{
A a1 = new A ();
A a2 = new A ("fix");
}
}
public class A
{
public A ()
{
System.Console.WriteLine("A()");
}
public A (string x = "default")
{
System.Console.WriteLine(x );
}
}
} |
Und hier das Resultat:
Man sieht also, dass der „am besten passende“ Constructor verwendet wird und der Default-Wert keine Verwendung findet. (wenn der Standard-Constructor A()
nicht existieren würde, würde natürlich der Default-Wert verwendet).
Versuch 2
Wenn man aber mit den Access Modifiers herumspielt ist das ganze nicht mehr so eindeutig. Setzen wir einmal den Access Modifier des Standard-Constructors auf internal
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| namespace ConstructorQuiz2
{
class Program
{
static void Main (string[] args )
{
A a1 = new A ();
A a2 = new A ("fix");
}
}
public class A
{
internal A ()
{
System.Console.WriteLine("A()");
}
public A (string x = "default")
{
System.Console.WriteLine(x );
}
}
} |
Das Ergebnis ist immer noch das selbe, hier hat der geänderte Access Modifier also noch keine Wirkung gezeigt.
Versuch 3
Versuchen wir jetzt aber mal von Aussen zuzugreifen:
1 2 3 4 5 6 7 8 9 10 11
| namespace ConstructorQuiz3
{
class Program
{
static void Main (string[] args )
{
ConstructorQuiz2 .A a1 = new ConstructorQuiz2 .A();
ConstructorQuiz2 .A a2 = new ConstructorQuiz2 .A("fix");
}
}
} |
Dieser Code muss mit einer Referenz auf den compilierten Code aus dem zweiten Beispiel enthalten. Dies erfolgt beim Command Line Tool csc
mit dem Parameter /r=<filename>
.
Das Resultat sieht nun anders aus:
Es wird jetzt also der Constructor mit dem Default-Wert aufgerufen, da der Standard-Constructor von der Dritt-Assembly nicht aufgerufen werden darf.
Fazit
Wann welcher Constructor verwendet wird ist nicht nur von den Parametern sondern auch von den Access Modifiern und dem Kontext abhängig.