Unter welchen Bedingungen soll ich die :base()
und :this()
Konstruktoraufrufe nach den Klammern meines Konstruktors (oder sogar an anderen Stellen im Code) machen. Wann sind diese Anrufe bewährte Praktiken und wann sind sie verbindlich?base() und this() Konstruktoren Best Practices
Antwort
: base(...)
Wenn Sie den Anruf an einen Basiskonstruktor auslassen wird es den Standard Basiskonstruktor automatisch aufrufen.
Es ist zwingend erforderlich, einen Basiskonstruktor explizit aufzurufen, wenn kein Standardkonstruktor vorhanden ist.
Auch wenn es einen Standardkonstruktor gibt, möchten Sie vielleicht immer noch einen anderen Konstruktor als den Standardkonstruktor aufrufen. In diesem Fall möchten Sie möglicherweise weiterhin base(foo, bar)
verwenden, um einen anderen Konstruktor als den Basiskonstruktor aufzurufen.
Ich halte es nicht für eine schlechte Praxis, base()
wegzulassen, wenn Sie den Standardkonstruktor der Basisklasse aufrufen möchten. Wenn Sie jedoch explizit sein möchten, sehe ich keinen Schaden darin. Es ist Geschmackssache.
: this(...)
Diese Syntax ermöglicht es Ihnen, einen Konstruktor mit einer anderen Signatur von einem anderen innerhalb der gleichen Klasse zu nennen. Dies ist niemals zwingend erforderlich, kann aber manchmal nützlich sein.
Ein Beispiel, wenn es nützlich sein kann, ist die Wiederverwendung von allgemeinem Code in den Konstruktoren. Zum Beispiel in C# 3.5 oder bevor Sie optionale Parameter auf einem Konstruktor simulieren möchten:
Foo(int x, int y)
{
this.x = x;
this.y = y;
}
Foo(int x) : this(x, 10) {} // y defaults to 10
Mit C# 4.0 optionale Parameter sind jetzt verfügbar, die die Notwendigkeit dieser Ansatz reduziert.
Eine alternative Möglichkeit, Code in Konstruktoren wiederzuverwenden, besteht darin, ihn in eine statische Funktion zu zerlegen, die von jedem Konstruktor aufgerufen wird, der sie verwenden möchte.
Suchen Sie nach "Konstruktor Verkettung in C#". Grundsätzlich sieht es wie folgt aus:
MyClass():base() //default constructor calling superclass constructor
{
}
MyClass(int arg):this() //non-basic constructor calling base constructor
{
//extra initialization
}
Es hilft Code-Duplizierung in Konstrukteuren entfernen - spalten sie in grundlegende und spezifische Teile.
Danke. "Konstrukteurverkettung" war der Begriff, an den ich mich nicht erinnern konnte. – JNappi
Sie verwenden: base(), wenn der Konstruktor der Basisklasse automatisch als erster Befehl Ihres Konstruktors aufgerufen werden soll. : this() ist ähnlich, ruft aber einen anderen Konstruktor derselben Klasse auf.
In base :() und this(): Sie können als Parameter konstante Werte übergeben, oder einen Ausdruck basierend auf Parametern Ihres Konstruktors.
Es ist obligatorisch, den Basiskonstruktor aufzurufen, wenn die Basisklasse keinen Standardkonstruktor hat (einen, der keine Parameter akzeptiert). Ich kenne keinen Fall, in dem: das() obligatorisch ist.
Zunächst einmal, wenn sie obligatorisch sind.
Wenn eine Klasse Derived
von einer Klasse abgeleitet ist Base
und Base
keinen Standard (parameterlos) Konstruktor, Derived
base()
explizit mit Parametern aufrufen müssen.
public class Base {
public Base(int i) { }
}
public class Derived : Base {
// public Derived() { } wouldn't work - what should be given for i?
public Derived() : base(7) { }
public Derived(int i) : base(i) { }
}
Wann ist es gute Praxis? Wann immer Sie einen anderen Konstruktor aufrufen möchten.
Angenommen, Sie fügen in meinem vorherigen Beispiel Inhalt zu den Konstruktoren in Abgeleitet hinzu.
public class Derived : Base {
// public Derived() { } wouldn't work - what should be given for i?
public Derived() : base(7) {
Console.WriteLine("The value is " + 7);
}
public Derived(int i) : base(i) {
Console.WriteLine("The value is " + i);
}
}
Sie bemerken die Duplizierung hier? Es ist einfacher, den Konstruktor this() aufzurufen.
public class Derived : Base {
// public Derived() { } wouldn't work - what should be given for i?
public Derived() : this(7) { }
public Derived(int i) : base(i) {
Console.WriteLine("The value is " + i);
}
}
Die Reihenfolge der Aufrufe im letzten Beispiel wäre also: "base (7)" und dann "Derived (7)" und dann "Derived()". Mit anderen Worten, der 'this (7)' -Teil selbst löst KEINE 'base()' aus (vorausgesetzt, es gab eine solche Basismethode). Ist es richtig? – RayLuo
Korrigieren; Die Konstruktoren sind immer verkettet, und jede Klasse ruft die Konstruktoren ihrer Basisklasse auf. Mit 'this' können Sie den anderen Konstruktor dieser Klasse wiederverwenden (der selbst 'base' verwendet, entweder implizit ohne Argumente oder explizit); Mit 'base' können Sie auswählen, welcher Basisklassenkonstruktor aufgerufen werden soll. – configurator
Verwendung base
wenn es Vererbung und eine Elternklasse bietet bereits die Funktionalität, die Sie erreichen wollen. Verwenden Sie this
Wenn Sie die aktuelle Entität (oder self) referenzieren möchten, verwenden Sie sie in der Header/Signatur des Konstruktors, wenn Sie die Funktionalität, die bereits in einem anderen Konstruktor definiert ist, nicht duplizieren möchten.
Grundsätzlich mit Basis und dies in einem Header-Konstruktor ist der Code DRY zu halten, ist es besser verwaltbar und weniger ausführlich
Hier machte ein absolut sinnlos Beispiel, aber ich denke, es ist die Idee zeigt zeigen, wie die zwei können benutzt werden.
class Person
{
public Person(string name)
{
Debug.WriteLine("My name is " + name);
}
}
class Employee : Person
{
public Employee(string name, string job)
: base(name)
{
Debug.WriteLine("I " + job + " for money.");
}
public Employee() : this("Jeff", "write code")
{
Debug.WriteLine("I like cake.");
}
}
Verbrauch:
var foo = new Person("ANaimi");
// output:
// My name is ANaimi
var bar = new Employee("ANaimi", "cook food");
// output:
// My name is ANaimi
// I cook food for money.
var baz = new Employee();
// output:
// My name is Jeff
// I write code for money.
// I like cake.
- 1. Best Practices in Bezug auf viele verschiedene Typen für Konstruktoren?
- 2. JavaScript Best Practices
- 3. Django- und Dateiberechtigungen: Best Practices?
- 4. Jira Konventionen und Best Practices
- 5. Bootstrap-Struktur und Best Practices
- 6. php und mysql, Best Practices
- 7. NGen und Gacutil Best Practices
- 8. Best Practices mit PhpUnit
- 9. AngularJS Best Practices - Styleguide
- 10. CFReadStreamHasBytesAvailable polling - Best Practices
- 11. nginx Konfiguration Best Practices
- 12. .net Diagnostics Best Practices?
- 13. DataReader Best-Practices
- 14. PivotalTracker Best Practices
- 15. JSON Design Best Practices
- 16. Initialisierung in Konstruktoren, Best Practice?
- 17. Repository Pattern Best Practices
- 18. Guice Best Practices und Anti-Muster
- 19. Java-Webanwendung Best Practices
- 20. NAnt Best Practices
- 21. JPA Best Practices
- 22. Rückwärtssuche Best Practices?
- 23. LinqToSql Best Practices
- 24. Serverseitige Anwendungskonfigurationssicherheit. Best Practices
- 25. Ereignisauslöser - Best Practices
- 26. PyLint Best Practices?
- 27. Angular2 Routing Best Practices
- 28. PHP-Entwicklungsumgebung Best Practices
- 29. Best Practices für Datenbanken
- 30. Regex Best Practices
sorry für die Mehrdeutigkeit ... Ich weiß, was diese Anrufe machen. Ich war einfach nicht klar über das Szenario, wenn ich diese Anrufe machen sollte oder muss. Orte, an denen ich, wenn ich sie nicht mache, entweder sofort zum Scheitern verurteilt bin oder einen latenten Fehler oder eine schlechte Codequalität. Ich hatte kürzlich solche Kopfschmerzen, deshalb wollte ich diese Szenarien klären. - – explorer