2016-05-24 12 views
0

Gibt es einen grundlegenden Unterschied bei der Einstellung von Objekteigenschaften mit oder ohne das Schlüsselwort new?Festlegen von Objekteigenschaften mit oder ohne C# 'new' Schlüsselwort

Das folgende ist ein Beispiel zur Veranschaulichung, was ich beziehe, unter Fall 1 und Fall 2 gezeigt. Wo immer möglich beabsichtigen Fall 2 zu verwenden (sieht ordentlich aus wie eine einzelne Aussage), konnte aber nicht sicher sein, ob die C# new Keyword hat Nachteile wie erhöhte Speicherauslastung. @Dennis_E Ich habe schon +1 gewählt ;-)

Amended Supplement: Danke euch allen mit prompten Kommentaren und Antworten. Sie wissen, Kommentare und Antworten jog ähnliche Punkte, an die Sie nie gedacht haben, als die Frage gestellt wurde. Verzeihen Sie mir für die Änderung, aber ich hoffe, Sie verstehen es.

Angenommen, der Code in Fall 1 und Fall 2 wird mehrfach verwendet (z. B. beim Navigieren auf einer Ansichtsseite), hat Fall 2 einen Nachteil beim Erhöhen des Speichers. Vielleicht mache ich hier eine falsche Annahme - schafft das "neue" Erzeugen der gleichen Variable ein neues Objekt? Vielleicht ist dies die grundlegende Frage.

public static class MyCache 
    { 
     public static NameIdObject MyCacheObject = new NameIdObject(); 
    } 

    public class NameIdObject 
    { 
     public string Name { get; set; } 
     public int Id { get; set; } 
    } 

    // Usage 1: without new keyword 

    MyCache.MyCacheObject.Name = "foo"; 
    MyCache.MyCacheObject.Id = 123; 

    // Usage 2: with new keyword 

    MyCache.MyCacheObject = new NameIdObject { Id = 123, Name = "foo" }; 
+0

beide Fälle ähneln sich hinsichtlich der Art und Weise, wie das Objekt konstruiert wird. "MyCache.MyCacheObject" wird immer initialisiert. –

+1

In Bezug auf die Erinnerung sind sie ziemlich gleich. Fall 2 verwendet faule Instanziierung, die die Zuweisung von Speicher verzögert. Dies ist jedoch eher eine Entscheidung des Designs. EDIT: Dies setzt voraus, dass Sie in Fall 2 das Objekt nicht direkt in "MyCache" initialisieren. –

Antwort

3

Das Schlüsselwort new hat nichts mit Einstellungseigenschaften zu tun. Es erstellt ein neues Objekt. Ein Objektinitialisierer kann jedoch nur in Verbindung mit dem Erstellen eines neuen Objekts verwendet werden.

Die Aussage

MyCache.MyCacheObject = new NameIdObject { Id = 123, Name = "foo" }; 

ist ein Objektinitialisierer. Es ist nur eine bequemere Art des Schreibens (und entspricht):

MyCache.MyCacheObject = new NameIdObject(); 
MyCache.MyCacheObject.Id = 123; 
MyCache.MyCacheObject.Name = "foo"; 

Ihr erstes Codebeispiel setzt nur die Eigenschaftswerte. Es instanziiert ein neues Objekt nicht. (Sie hätten das früher in einer separaten Anweisung getan)
Der grundlegende Unterschied ist also: Sie erstellen ein neues Objekt.

+0

Danke @Dennis_E - Nachdem ich die Antwort gelesen habe, kann meine Frage einige Änderungen erfordern. Angenommen, der Code in Fall 1 und Fall 2 wird mehrmals verwendet (z. B. wenn Sie auf eine Ansichtsseite navigieren), hat Fall 2 einen Nachteil beim Erhöhen des Speichers. Vielleicht mache ich hier eine falsche Annahme - erzeugt 'neu' die gleiche Variable ein anderes Objekt? Vielleicht ist dies die grundlegende Frage. – user2921851

+1

Sortieren von. Jedes Mal, wenn Sie "neu" aufrufen, erstellen Sie eine neue Instanz eines Objekts. Dies verursacht einen Rechenaufwand (und einen neuen Zeiger auf den Stapel usw.). Da es keine Referenzen mehr auf das alte Objekt gibt, wird es (irgendwann) vom Garbage Collector bereinigt, aber für eine kurze Zeit werden beide Objekte im Speicher existieren. – richzilla

+1

Ich war mir nicht sicher, ob ich verstanden habe. Jedes Mal, wenn Sie 'new' aufrufen, erstellen Sie ein neues Objekt. Ihre Variable wird dann auf dieses neue Objekt verweisen. Das alte Objekt ist immer noch im Speicher (aber nicht mehr von Ihrer Variablen referenziert). Wenn Sie nur die Eigenschaftswerte ändern, erstellen Sie kein neues Objekt. –

1

Eine gute Möglichkeit, dies zu überprüfen, ist, kleine Dateien zu schreiben, sie zu kompilieren und mit IL Spy zu überprüfen, was sie in der Zwischensprache machen. Wenn ich das mit diesem Fall mache, komme ich zu Dateien. Hier ist der C# -Code.

using System; 

namespace test 
{ 
    public class NameIdObject 
    { 
     public string Name { get; set; } 
     public int Id { get; set; } 
    } 

    public static class MyCache 
    { 
     public static NameIdObject MyCacheObject = new NameIdObject(); 
    } 

    public static class Program 
    { 
     public static void Main() 
     { 
      MyCache.MyCacheObject.Name = "foo"; 
      MyCache.MyCacheObject.Id = 123; 

     } 
    } 
} 

Fall 2

using System; 

namespace test 
{ 
    public class NameIdObject 
    { 
     public string Name { get; set; } 
     public int Id { get; set; } 
    } 

    public static class MyCache 
    { 
     public static NameIdObject MyCacheObject; 
    } 

    public static class Program 
    { 
     public static void Main() 
     { 
      MyCache.MyCacheObject = new NameIdObject { Id = 123, Name = "foo" }; 
     } 
    } 
} 

, wenn Sie diesen Trog der Entwickler Command Line kompilieren. Weitere Informationen hierzu finden Sie unter https://msdn.microsoft.com/en-us/library/78f4aasd.aspx. Sie können die Zwischensprache mit IL Spy sehen

Im Folgenden sind die Ergebnisse:

Fall 1

.namespace test 
{ 
    .class public auto ansi abstract sealed beforefieldinit test.MyCache 
     extends [mscorlib]System.Object 
    { 
     // Fields 
     .field public static class test.NameIdObject MyCacheObject 

     // Methods 
     .method private hidebysig specialname rtspecialname static 
      void .cctor() cil managed 
     { 
      // Method begins at RVA 0x207b 
      // Code size 11 (0xb) 
      .maxstack 8 

      IL_0000: newobj instance void test.NameIdObject::.ctor() 
      IL_0005: stsfld class test.NameIdObject test.MyCache::MyCacheObject 
      IL_000a: ret 
     } // end of method MyCache::.cctor 

    } // end of class test.MyCache 

    .class public auto ansi beforefieldinit test.NameIdObject 
     extends [mscorlib]System.Object 
    { 
     // Fields 
     .field private string '<Name>k__BackingField' 
     .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
      01 00 00 00 
     ) 
     .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
      01 00 00 00 00 00 00 00 
     ) 
     .field private int32 '<Id>k__BackingField' 
     .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
      01 00 00 00 
     ) 
     .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
      01 00 00 00 00 00 00 00 
     ) 

     // Methods 
     .method public hidebysig specialname 
      instance string get_Name() cil managed 
     { 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
       01 00 00 00 
      ) 
      // Method begins at RVA 0x2050 
      // Code size 7 (0x7) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: ldfld string test.NameIdObject::'<Name>k__BackingField' 
      IL_0006: ret 
     } // end of method NameIdObject::get_Name 

     .method public hidebysig specialname 
      instance void set_Name (
       string 'value' 
      ) cil managed 
     { 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
       01 00 00 00 
      ) 
      // Method begins at RVA 0x2058 
      // Code size 8 (0x8) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: ldarg.1 
      IL_0002: stfld string test.NameIdObject::'<Name>k__BackingField' 
      IL_0007: ret 
     } // end of method NameIdObject::set_Name 

     .method public hidebysig specialname 
      instance int32 get_Id() cil managed 
     { 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
       01 00 00 00 
      ) 
      // Method begins at RVA 0x2061 
      // Code size 7 (0x7) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: ldfld int32 test.NameIdObject::'<Id>k__BackingField' 
      IL_0006: ret 
     } // end of method NameIdObject::get_Id 

     .method public hidebysig specialname 
      instance void set_Id (
       int32 'value' 
      ) cil managed 
     { 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
       01 00 00 00 
      ) 
      // Method begins at RVA 0x2069 
      // Code size 8 (0x8) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: ldarg.1 
      IL_0002: stfld int32 test.NameIdObject::'<Id>k__BackingField' 
      IL_0007: ret 
     } // end of method NameIdObject::set_Id 

     .method public hidebysig specialname rtspecialname 
      instance void .ctor() cil managed 
     { 
      // Method begins at RVA 0x2072 
      // Code size 8 (0x8) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: call instance void [mscorlib]System.Object::.ctor() 
      IL_0006: nop 
      IL_0007: ret 
     } // end of method NameIdObject::.ctor 

     // Properties 
     .property instance string Name() 
     { 
      .get instance string test.NameIdObject::get_Name() 
      .set instance void test.NameIdObject::set_Name(string) 
     } 
     .property instance int32 Id() 
     { 
      .get instance int32 test.NameIdObject::get_Id() 
      .set instance void test.NameIdObject::set_Id(int32) 
     } 

    } // end of class test.NameIdObject 

    .class public auto ansi abstract sealed beforefieldinit test.Programm 
     extends [mscorlib]System.Object 
    { 
     // Methods 
     .method public hidebysig static 
      void Main() cil managed 
     { 
      // Method begins at RVA 0x2087 
      // Code size 31 (0x1f) 
      .maxstack 8 
      .entrypoint 

      IL_0000: nop 
      IL_0001: ldsfld class test.NameIdObject test.MyCache::MyCacheObject 
      IL_0006: ldstr "foo" 
      IL_000b: callvirt instance void test.NameIdObject::set_Name(string) 
      IL_0010: nop 
      IL_0011: ldsfld class test.NameIdObject test.MyCache::MyCacheObject 
      IL_0016: ldc.i4.s 123 
      IL_0018: callvirt instance void test.NameIdObject::set_Id(int32) 
      IL_001d: nop 
      IL_001e: ret 
     } // end of method Programm::Main 

    } // end of class test.Programm 

} 

Fall 2

.namespace test 
{ 
    .class public auto ansi abstract sealed beforefieldinit test.MyCache 
     extends [mscorlib]System.Object 
    { 
     // Fields 
     .field public static class test.NameIdObject MyCacheObject 

    } // end of class test.MyCache 

    .class public auto ansi beforefieldinit test.NameIdObject 
     extends [mscorlib]System.Object 
    { 
     // Fields 
     .field private string '<Name>k__BackingField' 
     .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
      01 00 00 00 
     ) 
     .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
      01 00 00 00 00 00 00 00 
     ) 
     .field private int32 '<Id>k__BackingField' 
     .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
      01 00 00 00 
     ) 
     .custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
      01 00 00 00 00 00 00 00 
     ) 

     // Methods 
     .method public hidebysig specialname 
      instance string get_Name() cil managed 
     { 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
       01 00 00 00 
      ) 
      // Method begins at RVA 0x2050 
      // Code size 7 (0x7) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: ldfld string test.NameIdObject::'<Name>k__BackingField' 
      IL_0006: ret 
     } // end of method NameIdObject::get_Name 

     .method public hidebysig specialname 
      instance void set_Name (
       string 'value' 
      ) cil managed 
     { 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
       01 00 00 00 
      ) 
      // Method begins at RVA 0x2058 
      // Code size 8 (0x8) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: ldarg.1 
      IL_0002: stfld string test.NameIdObject::'<Name>k__BackingField' 
      IL_0007: ret 
     } // end of method NameIdObject::set_Name 

     .method public hidebysig specialname 
      instance int32 get_Id() cil managed 
     { 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
       01 00 00 00 
      ) 
      // Method begins at RVA 0x2061 
      // Code size 7 (0x7) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: ldfld int32 test.NameIdObject::'<Id>k__BackingField' 
      IL_0006: ret 
     } // end of method NameIdObject::get_Id 

     .method public hidebysig specialname 
      instance void set_Id (
       int32 'value' 
      ) cil managed 
     { 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
       01 00 00 00 
      ) 
      // Method begins at RVA 0x2069 
      // Code size 8 (0x8) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: ldarg.1 
      IL_0002: stfld int32 test.NameIdObject::'<Id>k__BackingField' 
      IL_0007: ret 
     } // end of method NameIdObject::set_Id 

     .method public hidebysig specialname rtspecialname 
      instance void .ctor() cil managed 
     { 
      // Method begins at RVA 0x2072 
      // Code size 8 (0x8) 
      .maxstack 8 

      IL_0000: ldarg.0 
      IL_0001: call instance void [mscorlib]System.Object::.ctor() 
      IL_0006: nop 
      IL_0007: ret 
     } // end of method NameIdObject::.ctor 

     // Properties 
     .property instance string Name() 
     { 
      .get instance string test.NameIdObject::get_Name() 
      .set instance void test.NameIdObject::set_Name(string) 
     } 
     .property instance int32 Id() 
     { 
      .get instance int32 test.NameIdObject::get_Id() 
      .set instance void test.NameIdObject::set_Id(int32) 
     } 

    } // end of class test.NameIdObject 

    .class public auto ansi abstract sealed beforefieldinit test.Program 
     extends [mscorlib]System.Object 
    { 
     // Methods 
     .method public hidebysig static 
      void Main() cil managed 
     { 
      // Method begins at RVA 0x207b 
      // Code size 33 (0x21) 
      .maxstack 8 
      .entrypoint 

      IL_0000: nop 
      IL_0001: newobj instance void test.NameIdObject::.ctor() 
      IL_0006: dup 
      IL_0007: ldc.i4.s 123 
      IL_0009: callvirt instance void test.NameIdObject::set_Id(int32) 
      IL_000e: nop 
      IL_000f: dup 
      IL_0010: ldstr "foo" 
      IL_0015: callvirt instance void test.NameIdObject::set_Name(string) 
      IL_001a: nop 
      IL_001b: stsfld class test.NameIdObject test.MyCache::MyCacheObject 
      IL_0020: ret 
     } // end of method Program::Main 

    } // end of class test.Program 

} 

nun mit diesen Informationen Sie van Analysieren Sie, was das System mit Ihrem Code macht. Sie können in Fall 1 sehen, dass die Instanz von NameIdObject im Konstruktor des MyCache-Objekts erstellt wird.Während in Fall 2 die Instanz des NameIdObject in der Hauptfunktion des Programms erstellt wird.

Die Stelle, an der die Objektinstanz erstellt wird und damit die Zeit, zu der die Instanz erstellt wird, ist anders. Ich hoffe diese Hilfe zu entscheiden, welcher Fall für Ihr Programm am effizientesten ist.

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, mehr Einblick in die Antwort zu geben. – user2921851

Verwandte Themen