Customer c1 = new Customer {};
Dies ist ein leerer Objektinitialisierer. Gemäß der spec werden Objektinitialisierer den Standardkonstruktor aufrufen, sofern Sie den zu verwendenden Konstruktor nicht angeben. Da keine Initialisierung durchgeführt wird, wird sie genauso kompiliert wie der Standardkonstruktor.
Um die Frage zu beantworten, wenn '{}
act [s] wie ()
beim Erstellen eines neuen Objekts in C#', müssen wir ins Detail gehen. Für alles, was Ihnen wichtig ist, enthalten die resultierenden Objekte dieselben Daten, aber die generierte IL ist nicht identisch.
Das folgende Beispiel
namespace SO28254462
{
class Program
{
class Customer
{
private readonly Foo foo = new Foo();
public string name;
public Customer()
{
}
public Customer(string id)
{
this.ID = id;
}
public string ID { get; set; }
public Foo Foo
{
get
{
return this.foo;
}
}
}
class Foo
{
public string Bar { get; set; }
}
static void Main(string[] args)
{
Customer c1 = new Customer { };
Customer c2 = new Customer();
Customer c3 = new Customer { name = "John", ID = "ABC", Foo = { Bar = "whatever" } };
Customer c4 = new Customer();
c4.name = "John";
c4.ID = "ABC";
c4.Foo.Bar = "whatever";
Customer c5 = new Customer("ABC") { name = "John", Foo = { Bar = "whatever" } };
Customer c6 = new Customer("ABC");
c6.name = "John";
c6.Foo.Bar = "whatever";
}
}
}
dieser IL kompilieren (nur Hauptmethode, Debug ohne Optimierungen)
.method private hidebysig static
void Main (
string[] args
) cil managed
{
// Method begins at RVA 0x2050
// Code size 201 (0xc9)
.maxstack 2
.entrypoint
.locals init (
[0] class SO28254462.Program/Customer c1,
[1] class SO28254462.Program/Customer c2,
[2] class SO28254462.Program/Customer c3,
[3] class SO28254462.Program/Customer c4,
[4] class SO28254462.Program/Customer c5,
[5] class SO28254462.Program/Customer c6,
[6] class SO28254462.Program/Customer '<>g__initLocal0',
[7] class SO28254462.Program/Customer '<>g__initLocal1'
)
IL_0000: nop
IL_0001: newobj instance void SO28254462.Program/Customer::.ctor()
IL_0006: stloc.0
IL_0007: newobj instance void SO28254462.Program/Customer::.ctor()
IL_000c: stloc.1
IL_000d: newobj instance void SO28254462.Program/Customer::.ctor()
IL_0012: stloc.s '<>g__initLocal0'
IL_0014: ldloc.s '<>g__initLocal0'
IL_0016: ldstr "John"
IL_001b: stfld string SO28254462.Program/Customer::name
IL_0020: ldloc.s '<>g__initLocal0'
IL_0022: ldstr "ABC"
IL_0027: callvirt instance void SO28254462.Program/Customer::set_ID(string)
IL_002c: nop
IL_002d: ldloc.s '<>g__initLocal0'
IL_002f: callvirt instance class SO28254462.Program/Foo SO28254462.Program/Customer::get_Foo()
IL_0034: ldstr "whatever"
IL_0039: callvirt instance void SO28254462.Program/Foo::set_Bar(string)
IL_003e: nop
IL_003f: ldloc.s '<>g__initLocal0'
IL_0041: stloc.2
IL_0042: newobj instance void SO28254462.Program/Customer::.ctor()
IL_0047: stloc.3
IL_0048: ldloc.3
IL_0049: ldstr "John"
IL_004e: stfld string SO28254462.Program/Customer::name
IL_0053: ldloc.3
IL_0054: ldstr "ABC"
IL_0059: callvirt instance void SO28254462.Program/Customer::set_ID(string)
IL_005e: nop
IL_005f: ldloc.3
IL_0060: callvirt instance class SO28254462.Program/Foo SO28254462.Program/Customer::get_Foo()
IL_0065: ldstr "whatever"
IL_006a: callvirt instance void SO28254462.Program/Foo::set_Bar(string)
IL_006f: nop
IL_0070: ldstr "ABC"
IL_0075: newobj instance void SO28254462.Program/Customer::.ctor(string)
IL_007a: stloc.s '<>g__initLocal1'
IL_007c: ldloc.s '<>g__initLocal1'
IL_007e: ldstr "John"
IL_0083: stfld string SO28254462.Program/Customer::name
IL_0088: ldloc.s '<>g__initLocal1'
IL_008a: callvirt instance class SO28254462.Program/Foo SO28254462.Program/Customer::get_Foo()
IL_008f: ldstr "whatever"
IL_0094: callvirt instance void SO28254462.Program/Foo::set_Bar(string)
IL_0099: nop
IL_009a: ldloc.s '<>g__initLocal1'
IL_009c: stloc.s c5
IL_009e: ldstr "ABC"
IL_00a3: newobj instance void SO28254462.Program/Customer::.ctor(string)
IL_00a8: stloc.s c6
IL_00aa: ldloc.s c6
IL_00ac: ldstr "John"
IL_00b1: stfld string SO28254462.Program/Customer::name
IL_00b6: ldloc.s c6
IL_00b8: callvirt instance class SO28254462.Program/Foo SO28254462.Program/Customer::get_Foo()
IL_00bd: ldstr "whatever"
IL_00c2: callvirt instance void SO28254462.Program/Foo::set_Bar(string)
IL_00c7: nop
IL_00c8: ret
} // end of method Program::Main
Wie wir in identische sehen, haben die ersten beiden Customer
Initialisierungen umgewandelt IL (IL_0001 bis IL_000c). Danach wird es interessanter: Von IL_000d bis IL_0041 sehen wir, dass ein neues Objekt erstellt und der unsichtbaren temporären Variablen <>g__initLocal0
zugewiesen wird und erst danach der resultierende Wert c3
zugewiesen wird. So wird der Objektinitialisierer vom C# -Compiler implementiert. Der Unterschied zum manuellen Festlegen der öffentlichen Eigenschaften nach dem Instanziieren des Objekts ist offensichtlich, wenn Sie sich ansehen, wie c4
von IL_0042 zu IL_006a initialisiert wird - es gibt keine temporäre Variable.
IL_0070 bis zum Ende entsprechen den vorherigen Beispielen, außer dass sie einen nicht standardmäßigen Konstruktor in Kombination mit Objektinitialisierern verwenden. Wie Sie vielleicht erwarten, wird es einfach wie zuvor kompiliert, aber mit dem angegebenen Konstruktor.
Lange Rede, kurzer Sinn: Das Ergebnis ist aus der Sicht eines C# Entwicklers im Grunde dasselbe. Objektinitialisierer sind einfache syntaktische Zucker- und Compilertricks, die helfen können, den Code leichter lesbar zu machen. In FWIW ist die resultierende IL jedoch nicht identisch mit der manuellen Initialisierung der Eigenschaften. Dennoch sollten die Kosten der unsichtbaren temporären Variablen, die vom Compiler ausgegeben werden, in fast allen C# -Programmen nicht signifikant sein.
Sie * können * Werte in der ctor ['()'] übergeben, wenn Sie eine Überladung bereitstellen, um sie zu akzeptieren und zu verwenden. die geschweiften Klammern sind zum Initialisieren – Plutonix
Keine Antwort, weil Sie bereits diese, nur einen Kommentar: '{}' bietet eine Möglichkeit, Werte zu assutieren, im Grunde nichts mehr als eine Kurzschrift, um das Objekt zuerst zu instanziieren und dann die Werte nacheinander zuzuweisen . Der Konstrukteur ist jedoch in keiner Weise darauf beschränkt. Es liegt ganz bei Ihnen, welche Argumente Sie übergeben und ob Sie diese Argumente verwenden, um Standardwerte zuzuordnen, Berechnungen durchzuführen oder andere Teile Ihres Codes aufzurufen. –