it-swarm.com.de

Sollten wir immer einen Standardkonstruktor in die Klasse aufnehmen?

Diese Frage wurde mir von einem Kollegen gestellt, ob wir immer einen Standardkonstruktor in eine Klasse aufnehmen sollten. Wenn ja warum? Wenn nein, warum nicht?

Beispiel

public class Foo {

    Foo() { }

    Foo(int x, int y) {
        ...
    } 

}

Ich bin auch daran interessiert, dies von Experten zu erfahren.

63
Moon

Sie müssen bedenken, dass der Compiler einen Standardkonstruktor für Sie generiert, wenn Sie keinen überladenen Konstruktor angeben. Das heißt, wenn Sie gerade haben

public class Foo
{ 
} 

Der Compiler generiert dies als:

public class Foo
{ 
    public Foo() { }  
} 

Sobald Sie jedoch den anderen Konstruktor hinzufügen

public class Foo
{ 
    public Foo(int x, int y)
    { 
        // ... 
    }  
} 

Der Compiler generiert den Standardkonstruktor nicht mehr automatisch für Sie. Wenn die Klasse bereits in anderem Code verwendet wurde, der auf dem Standardkonstruktor Foo f = new Foo(); basierte, würde dieser Code jetzt beschädigt.

Wenn Sie nicht möchten, dass jemand die Klasse initialisieren kann, ohne Daten anzugeben, sollten Sie einen Standardkonstruktor erstellen, der private ist, um explizit darauf hinzuweisen, dass Instanzen nicht mit Eingabedaten erstellt werden.

Es kann jedoch vorkommen, dass ein Standardkonstruktor (öffentlich oder privat) bereitgestellt werden muss. Wie bereits erwähnt, erfordern einige Serialisierungstypen einen Standardkonstruktor. Es gibt auch Zeiten, zu denen eine Klasse mehrere parametrisierte Konstruktoren hat, aber auch eine Initialisierung auf niedrigerer Ebene erfordert. In diesem Fall kann ein privater Standardkonstruktor verwendet werden, der von den parametrisierten Konstruktoren her verkettet wird.

public class Foo
{
   private Foo()
   {
      // do some low level initialization here
   }

   public Foo(int x, int y)
      : this()
   {
      // ...
   }

   public Foo(int x, int y, int z)
      : this()
   {
      // ...
   }
}
105
Scott Dorman

Einige Dinge (wie die Serialisierung) erfordern einen Standardkonstruktor. Abgesehen davon sollte ein Standardkonstruktor jedoch nur hinzugefügt werden, wenn dies sinnvoll ist.

Wenn zum Beispiel die Eigenschaften Foo.X und Foo.Y nach der Erstellung unveränderlich sind, ist ein Standardkonstruktor nicht wirklich sinnvoll. Selbst wenn es für ein 'leeres' Foo verwendet würde, wäre ein statischer Empty-Accessor auffindbarer.

19
Richard Szalay

Ich würde nein sagen, definitiv nicht immer. Angenommen, Sie haben eine Klasse mit einigen Readonly-Feldern, die mit einem bestimmten Wert initialisiert werden müssen, und es gibt keine vernünftigen Standardwerte (oder möchten Sie nicht, dass dies der Fall ist). In diesem Szenario halte ich keinen parameterlosen Konstruktor für sinnvoll.

12
Dan Tao

Ein Standardkonstruktor ist nur dann sinnvoll, wenn es sinnvoll ist, ein solches Objekt zu haben.

Wenn Sie aus einem solchen Konstruktor ein Objekt erzeugen, das nicht in einem gültigen Zustand ist, können Sie nur einen Fehler einführen.

5
Jon Hanna

Ja Es ist besser, einen Standardkonstruktor zu verwenden, um Verwechslungen zu vermeiden. Ich habe gesehen, dass Leute nichts innerhalb eines Standardkonstruktors tun (selbst in den eigenen Klassen von Microsoft), aber trotzdem behalten, da Objekte automatisch den Standard (Typ) erhalten. Die Klassen, in denen der Standardkonstruktor .NET nicht angegeben ist, fügen sie automatisch für Sie hinzu. 

Die Serialisierung erfordert den Default-Konstruktor, wenn Sie vorhandene Serialisierer verwenden, da dies für allgemeine Serialisierer sinnvoll ist. Andernfalls müssen Sie Ihre eigene Implementierung erstellen. 

1
abhishek

Beachten Sie als Randbemerkung, wenn Sie struct anstelle von class verwenden. Beachten Sie, dass es no gibt, um den Standardkonstruktor auszulassen, und es ist auch nicht möglich, ihn selbst zu definieren. Stellen Sie also unabhängig davon, welche Konstruktoren Sie definieren, sicher, dass das Standardzustand der Struktur (wenn alle Variablen auf ihren Standardzustand gesetzt sind (normalerweise 0 für Wertetypen und Null für Referenztypen), wird die Implementierung der Struktur nicht beeinträchtigt.

1

In den meisten Fällen ist ein Standardkonstruktor eine gute Idee. Da Sie jedoch das Wort "immer" verwenden, genügt ein Gegenbeispiel. Wenn Sie sich das Framework anschauen, finden Sie reichlich. Beispiel: System.Web.HttpContext.

0
Joe

Ein generischer Typ kann nur mit C # -Mitteln (ohne Reflektion) instanziiert werden, wenn er einen Standardkonstruktor hat. Außerdem muss die generische Typeinschränkung new() angegeben werden:

void Construct<T>()
    where T : new()
{
    var t = new T();
    ...
}

Das Aufrufen dieser Methode mit einem Typ als generisches Typargument ohne Standardkonstruktor führt zu einem Compiler-Fehler.