Frage

Ist es besser Klasse Membervariablen auf Deklaration zu initialisieren

private List<Thing> _things = new List<Thing>();
private int _arb = 99;

oder im Standard-Konstruktor?

private List<Thing> _things;
private int _arb;

public TheClass()
{
  _things = new List<Thing>();
  _arb = 99;
}

Ist es einfach eine Frage des Stils oder gibt es Leistungskompromisse, die eine oder die andere?

War es hilfreich?

Lösung

In Bezug auf Leistung, gibt es keinen wirklichen Unterschied; Feld initializers als Konstruktor Logik implementiert. Der einzige Unterschied ist, dass Feld initializers geschehen, bevor eine „Basis“ / „dieses“ Konstruktor.

Der Konstruktor Ansatz kann mit automatisch implementierte Eigenschaften (Feld initializers nicht kann) verwendet werden - d. H

[DefaultValue("")]
public string Foo {get;set;}
public Bar() { // ctor
  Foo = "";
}

Other than that, ich neige dazu, die Feldinitialisierer Syntax zu bevorzugen; Ich finde es immer wieder Dinge lokalisieren - d. H

private readonly List<SomeClass> items = new List<SomeClass>();
public List<SomeClass> Items {get {return items;}}

Ich muss nicht auf die Jagd gehen nach oben und unten zu finden, wo es zugeordnet ist ...

Die offensichtliche Ausnahme ist, wo Sie komplexe Logik durchführen müssen oder mit Konstruktorparameter beschäftigen - in diesem Fall Konstruktor-basierte Initialisierung ist der Weg zu gehen. Ebenso, wenn Sie mehrere Konstruktoren haben, wäre es besser, für die Felder immer auf die gleiche Art und Weise fertig - so könnte man ctors haben wie:

public Bar() : this("") {}
public Bar(string foo) {Foo = foo;}

edit: als Neben Kommentar zu beachten, dass in den oben genannten, wenn es andere Felder sind mit Feld initializers (nicht dargestellt), dann sind sie nur direkt in der Konstrukteurs initialisiert, die base(...) nennen - das heißt, den public Bar(string foo) Ctor. Der andere Konstruktor tut nicht laufen Feld initializers, da sie weiß, dass sie von der this(...) Ctor fertig sind.

Andere Tipps

Eigentlich Feld Initialisierungen, wie Sie zeigen ein praktisches Kürzel. Der Compiler tatsächlich kopiert den Code für die Initialisierung in den Anfang jedes Instanzkonstruktors, die Sie für Ihre Art zu definieren.

Diese zwei Auswirkungen hat. Zunächst Code alle Felder Initialisierung in jedem Konstruktor dupliziert wird, und zweitens, jeder Code, den Sie in Ihren Konstrukteuren umfassen Felder auf bestimmte Werte in der Tat initialisieren die Felder neu zuweisen

So Performance-weise, und im Hinblick auf die kompilierten Code-Größe, sind Sie besser dran Feld initializers in Konstrukteuren zu bewegen.

Auf der anderen Seite, die Auswirkungen auf die Leistung und Code ‚aufblasen‘ wird in der Regel vernachlässigbar sein, und die Feldinitialisierer Syntax hat den wichtigen Vorteil, das Risiko der Verringerung, die Sie vergessen könnten einige Feld in einem Ihrer Konstrukteure zu initialisieren.

Eine große Einschränkung mit Feld initializers ist, dass es keine Möglichkeit, sie in einem Try-finally Block zu wickeln. Wenn eine Ausnahme in einem Feldinitialisierer geworfen wird, werden alle Ressourcen, die in früheren initializers zugewiesen wurden aufgegeben werden; es gibt keine Möglichkeit, es zu verhindern. Andere Fehler im Aufbau behandelt werden können, wenn ungeschickt, durch eine geschützte Basiskonstruktor eine IDisposable durch Bezugnahme Kauf nehmen zu müssen, und zeigt sie an, mich als seine erste Operation. Man kann dann vermeiden Sie den Konstruktor, außer durch Factory-Methoden aufrufen, die im Falle einer Ausnahme Entsorgen Sie rufen auf dem teilweise erstellte Objekt. Dieser Schutz wird für die Bereinigung von IDisposables erstellt in abgeleiteten Klasse initializers erlauben, wenn der Hauptklasse Konstruktor nicht nach „Schmuggel out“ einen Verweis auf das neue Objekt. Leider gibt es keine Möglichkeit, einen solchen Schutz zu bieten, wenn ein Feldinitialisierer ausfällt.

entweder Feld initializers verwenden oder eine Init () Funktion erstellen. Das Problem mit diesen Dinge in Ihrem Konstruktor setzen ist, dass, wenn Sie jemals einen zweiten Konstruktor hinzufügen müssen, können Sie mit Copy / Paste-Code am Ende (oder Sie übersehen es und mit nicht initialisierten Variablen am Ende).

Ich würde entweder initialisieren, wo erklärt. Oder den Konstruktor haben (s) rufen eine Init () Funktion.

Zum Beispiel Variablen, es ist vor allem eine Frage des Stils (I einen Konstruktor lieber mit). Für statische Variablen gibt es eine Leistungsvorteil rel="nofollow Initialisieren Inline (nicht immer möglich, natürlich).

Es ist wirklich an Ihnen.
Ich sie oft inline initialisieren, Ursache Ich mag es nicht einen Konstruktor haben, wenn ich wirklich nicht, man braucht (Ich mag kleine Klassen!).

Auf hinzugefügt Punkt auf die oben - Sie haben immer einen Konstruktor, wenn Klassen implementieren, die eine Implementierung haben. Wenn Sie nicht erklären, man dann das Standard-Instruktor vom Compiler [public Foo () {}] zu entnehmen ist; ein Konstruktor, der keine Argumente hat.

Oft Ich mag beiden Ansätze bieten. Lassen Sie Konstrukteure für diejenigen, die sie verwenden möchten, und lassen Sie das Feld Initializers für Situationen, in denen Sie eine vereinfachte oder Default-Implementierung Ihrer Klasse / Typ verwenden möchten. Dies erhöht die Flexibilität, um Ihren Code. Beachten Sie, dass jemand das Standard Feldinitialisierer verwenden können, wenn sie wählen ... sicher sein, es manuell zu erklären, wenn Sie mehr als einen Konstruktor bieten - public Foo () {}

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top