2012-05-13 5 views

Antwort

4

Ein Argument im Konstruktor (Nicht-Standardkonstruktor), für mich, ermöglicht ein besseres Testen. Sie können bestimmte Daten in ein Mitgliedsfeld "injizieren", die Sie nicht unbedingt tun könnten, ohne dieses Mitglied öffentlich (oder zumindest intern) zu machen oder einen zweiten Aufruf mit einer "Setter" -Eigenschaft durchzuführen.

Da Sie mehrere Konstruktoren haben können, könnten Sie eine zweite zum Testen in Verbindung mit einem Standardkonstruktor haben, wenn Sie wirklich wollen.

Es gibt keine wirklichen Leistungsprobleme, als dass Sie einen separaten Aufruf zum späteren Auffüllen von Daten oder weniger wartbaren Code mit mehreren Aufrufen der Klasse vornehmen müssen (eine zum Erstellen des Objekts, die zweite zum Auffüllen des Elements)).

EDIT: Ich erkannte, dass ich sorta die falsche Frage beantwortet. Ich dachte, er würde nach dem Unterschied zwischen Standard- und Nichtstandardkonstruktoren fragen. Jetzt sehe ich, dass es über einen Standardkonstruktor war, der das Mitglied im Konstruktor vs. in der Mitgliedsdeklaration ... initialisiert

+0

ok, was ist mit Leistung und Speicherzuweisung? – retide

+1

Das macht keinen Sinn. Sie können etwas nicht injizieren, wenn Sie das nicht als Konstruktor anbieten, und ein bestimmter Konstruktor zum Testen ist Code-Geruch (es zeigt auf eine Klasse mit zu vielen direkten Abhängigkeiten). Wenn Sie die Klasse wirklich entkoppeln möchten, nehmen Sie alle Parameter, die möglicherweise als Schnittstellen geändert werden müssen. – Femaref

+0

Vielleicht, aber im Zusammenhang mit seiner Frage mit dieser Member-Variable, ist es sicherlich eine Option. Ich stimme zu, in dem Fall, wo Sie viele Eigenschaften haben können, erstellen Sie eine Schnittstelle und übergeben Sie diese. – Killnine

1

Die zwei sind äquivalent. Der Compiler verschiebt die Initialisierung solcher Elemente in den Konstruktor (statischer Konstruktor, wenn das Element statisch ist). Ich würde nicht sagen, dass es einen allgemein besten Weg gibt, es zu tun - sei einfach konsistent, wo immer es möglich ist, und wenn es in der Situation mehr Sinn macht, benutze es.

1

Initialisieren Sie Instanzmitglieder im Konstruktor, initialisieren Sie Klassenmitglieder in der Deklaration. AFAIK dies ist (nur) die Konvention, und es gibt keine Leistungseinbußen. IMHO sollte dies in die Sprachregel (Syntax/Semantik) gezwungen werden.

10

Sie sind ziemlich gleichwertig (irgendwelche Unterschiede in Bezug auf Leistung und Speichernutzung sind vernachlässigbar). Der einzige wirkliche Unterschied ist, dass, wenn Sie tun:

private List<string>name = new List<string>(); 

... immer die Zuordnung egal was passiert, Konstruktor verwendet wird, um eine Instanz des Objekts zu erstellen. Wenn Sie die Zuweisung innerhalb eines Konstruktors ausführen, geschieht dies nur, wenn dieser spezifische Konstruktor verwendet wird.

Wenn Sie mehrere Konstruktoren haben, aber Sie möchten immer name genau auf die gleiche Weise initialisieren, ist es ein bisschen kürzer, das erste Formular zu verwenden, als es explizit in jedem Konstruktor zu initialisieren.

Als allgemeine Regel bevorzuge ich jedoch die Initialisierung von Feldern in den Konstruktorimplementierungen, auch wenn es den Code in manchen Fällen ausführlicher macht.

+0

Als eine Randnotiz bewegt der Compiler tatsächlich jeden Elementinitialisierungscode zu allen Konstruktoren. Dies bedeutet, dass es absolut keine Unterschiede zwischen Performance- und Speicherausnutzungs-Anforderungen geben sollte, außer dass die Anweisungen für jeden verwendeten Konstruktor wiederholt werden (dies wäre nur von Bedeutung, wenn Sie Initialisierungsanweisungen in Megabyte für Instanz-Member haben) auf diese Weise und mehrere Konstruktoren deklariert). –

+0

Dies ist eine sehr gute Erklärung, und beantwortet tatsächlich die Frage;) +1 – Killnine

+0

@TimS. Haben Sie irgendwelche Beweise, um die Behauptung zu bestätigen, dass Feldinitialisierer zu Konstruktoren verschoben werden? Es erscheint mir sehr unwahrscheinlich, da [Feldinitialisierer und Konstruktoren von Basisklassen nicht in der gleichen Reihenfolge aufgerufen werden] (http://blogs.msdn.com/b/ericlippert/archive/2008/02/15/why-do -initialisers-run-in-der-umgekehrte-Reihenfolge-als-Konstruktor-part-one.aspx). Der Feldinitialisierer führt * vor * den Feldinitialisierern der Basisklasse und vor seinem Konstruktor; Der Konstruktor führt * nach * dem Basisklassenkonstruktor aus. – phoog

1

initialisieren Felder im Konstruktor ermöglicht es Ihnen auch dieses Problem zu vermeiden:

class MyClass 
{ 
    private List<string> _list = new List<string>(); 
    public MyClass() 
    { 
     //some logic here 
    } 
    public MyClass(List<string> initialList) : this() 
    { 
     _list = initialList; 
    } 
} 

Mit diesem Code, wenn Sie die zweite Konstruktor aufrufen, werden Sie unnötig eine Liste erstellen, die fast sofort aufgegeben und machte Anspruch auf Müllabfuhr.

Verwandte Themen