Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Konstruktoren sind besondere Methoden zum Initialisieren von Typen und Erstellen von Instanzen von Typen. Mit einem Typkonstruktor werden statische Daten in einem Typ initialisiert. Ein Typkonstruktor wird von der Common Language Runtime (CLR) aufgerufen, bevor Instanzen des Typs erstellt werden. Typkonstruktoren sind static (Shared in Visual Basic) und können keine Parameter akzeptieren. Mit einem Instanzkonstruktor werden Instanzen eines Typs erstellt. Instanzkonstruktoren können Parameter akzeptieren, müssen dies jedoch nicht. Ein Instanzkonstruktor ohne Parameter wird als Standardkonstruktor bezeichnet.
Die folgenden Richtlinien beschreiben die empfohlenen Vorgehensweisen zum Erstellen von Konstruktoren.
Stellen Sie einfache Konstruktoren und nach Möglichkeit Standardkonstruktoren bereit. Ein einfacher Konstruktor verfügt über eine sehr geringe Anzahl von Parametern, und alle Parameter sind primitive Typen oder Enumerationen.
Verwenden Sie eine statische Factorymethode statt eines Konstruktors, wenn die Semantik der gewünschten Operation nicht direkt der Erstellung einer neuen Instanz entspricht oder wenn die Befolgung der Richtlinien zum Konstruktorentwurf aus anderen Gründen unangebracht erscheint.
Legen Sie Haupteigenschaften über Konstruktorparameter fest.
Das Festlegen von Eigenschaften mit dem Konstruktor sollte dem direkten Festlegen der Eigenschaften entsprechen. Im folgenden Codebeispiel wird eine EmployeeRecord-Klasse veranschaulicht, die durch den Aufruf eines Konstruktors oder durch direktes Festlegen von Eigenschaften initialisiert werden kann. Die EmployeeManagerConstructor-Klasse veranschaulicht das Initialisieren eines EmployeeRecord-Objekts mithilfe des Konstruktors. Die EmployeeManagerProperties-Klasse veranschaulicht das Initialisieren eines EmployeeRecord-Objekts mithilfe von Eigenschaften. Die Tester-Klasse veranschaulicht, dass die Objekte unabhängig vom verwendeten Verfahren denselben Zustand aufweisen.
Imports System
Imports System.Collections.ObjectModel
namespace Examples.DesignGuidelines.Constructors
' This Class can get its data either by setting
' properties or by passing the data to its constructor.
Public Class EmployeeRecord
private employeeIdValue as Integer
private departmentValue as Integer
Public Sub New()
End Sub
Public Sub New(id as Integer, department as Integer)
Me.employeeIdValue = id
Me.departmentValue = department
End Sub
Public Property Department as Integer
Get
Return departmentValue
End Get
Set
departmentValue = value
End Set
End Property
Public Property EmployeeId as Integer
Get
Return employeeIdValue
End Get
Set
employeeIdValue = value
End Set
End Property
Public Sub DisplayData()
Console.WriteLine("{0} {1}", EmployeeId, Department)
End Sub
End Class
' This Class creates Employee records by passing
' argumemnts to the constructor.
Public Class EmployeeManagerConstructor
Dim employees as Collection(Of EmployeeRecord) = _
new Collection(Of EmployeeRecord)()
Public Sub AddEmployee(employeeId as Integer, department as Integer)
Dim record as EmployeeRecord = new EmployeeRecord(employeeId, department)
employees.Add(record)
record.DisplayData()
End Sub
End Class
' This Class creates Employee records by setting properties.
Public Class EmployeeManagerProperties
Dim employees as Collection(Of EmployeeRecord)= _
new Collection(Of EmployeeRecord)()
Public Sub AddEmployee(employeeId as Integer, department as Integer)
Dim record as EmployeeRecord = new EmployeeRecord()
record.EmployeeId = employeeId
record.Department = department
employees.Add(record)
record.DisplayData()
End Sub
End Class
Public Class Tester
' The following method creates objects with the same state
' using the two different approaches.
Public Shared Sub Main()
Dim byConstructor as EmployeeManagerConstructor = _
new EmployeeManagerConstructor()
byConstructor.AddEmployee(102, 102)
Dim byProperties as EmployeeManagerProperties = _
new EmployeeManagerProperties()
byProperties.AddEmployee(102, 102)
End Sub
End Class
End Namespace
using System;
using System.Collections.ObjectModel;
namespace Examples.DesignGuidelines.Constructors
{
// This class can get its data either by setting
// properties or by passing the data to its constructor.
public class EmployeeRecord
{
private int employeeId;
private int department;
public EmployeeRecord()
{
}
public EmployeeRecord(int id, int department)
{
this.employeeId = id;
this.department = department;
}
public int Department
{
get {return department;}
set {department = value;}
}
public int EmployeeId
{
get {return employeeId;}
set {employeeId = value;}
}
public void DisplayData()
{
Console.WriteLine("{0} {1}", EmployeeId, Department);
}
}
// This class creates Employee records by passing
// argumemnts to the constructor.
public class EmployeeManagerConstructor
{
Collection<EmployeeRecord > employees = new Collection<EmployeeRecord>();
public void AddEmployee(int employeeId, int department)
{
EmployeeRecord record = new EmployeeRecord(employeeId, department);
employees.Add(record);
record.DisplayData();
}
}
// This class creates Employee records by setting properties.
public class EmployeeManagerProperties
{
Collection<EmployeeRecord > employees = new Collection<EmployeeRecord>();
public void AddEmployee(int employeeId, int department)
{
EmployeeRecord record = new EmployeeRecord();
record.EmployeeId = employeeId;
record.Department = department;
employees.Add(record);
record.DisplayData();
}
}
public class Tester
{
// The following method creates objects with the same state
// using the two different approaches.
public static void Main()
{
EmployeeManagerConstructor byConstructor =
new EmployeeManagerConstructor();
byConstructor.AddEmployee(102, 102);
EmployeeManagerProperties byProperties =
new EmployeeManagerProperties();
byProperties.AddEmployee(102, 102);
}
}
}
using namespace System;
using namespace System::Collections::ObjectModel;
namespace Examples { namespace DesignGuidelines { namespace Constructors
{
// This class can get its data either by setting
// properties or by passing the data to its constructor.
public ref class EmployeeRecord
{
private:
int employeeId;
int department;
public:
EmployeeRecord()
{
}
EmployeeRecord(int id, int department)
{
this->employeeId = id;
this->department = department;
}
property int Department
{
int get() {return department;}
void set(int value) {department = value;}
}
property int EmployeeId
{
int get() {return employeeId;}
void set(int value) {employeeId = value;}
}
void DisplayData()
{
Console::WriteLine("{0} {1}", EmployeeId, Department);
}
};
// This class creates Employee records by passing
// argumemnts to the constructor.
public ref class EmployeeManagerConstructor
{
private:
Collection<EmployeeRecord^>^ employees;
public:
EmployeeManagerConstructor()
{
employees = gcnew Collection<EmployeeRecord^>();
}
void AddEmployee(int employeeId, int department)
{
EmployeeRecord^ record = gcnew EmployeeRecord(employeeId, department);
employees->Add(record);
record->DisplayData();
}
};
// This class creates Employee records by setting properties.
public ref class EmployeeManagerProperties
{
private:
Collection<EmployeeRecord^>^ employees;
public:
EmployeeManagerProperties()
{
employees = gcnew Collection<EmployeeRecord^>();
}
void AddEmployee(int employeeId, int department)
{
EmployeeRecord^ record = gcnew EmployeeRecord();
record->EmployeeId = employeeId;
record->Department = department;
employees->Add(record);
record->DisplayData();
}
};
public ref class Tester
{
// The following method creates objects with the same state
// using the two different approaches.
public:
static void Main()
{
EmployeeManagerConstructor^ byConstructor =
gcnew EmployeeManagerConstructor();
byConstructor->AddEmployee(102, 102);
EmployeeManagerProperties^ byProperties =
gcnew EmployeeManagerProperties();
byProperties->AddEmployee(102, 102);
}
};
}}}
Beachten Sie, dass in diesen Beispielen und in einer gut entworfenen Bibliothek mit beiden Verfahren Objekte erstellt werden, die denselben Zustand aufweisen. Welche Vorgehensweise ein Entwickler bevorzugt, ist ohne Belang.
Verwenden Sie denselben Namen für Konstruktorparameter und eine Eigenschaft, wenn die Konstruktorparameter lediglich zum Festlegen der Eigenschaft verwendet werden. Diese Parameter und die Eigenschaften sollten sich nur durch die Groß-/Kleinschreibung unterscheiden.
Diese Richtlinie wird im vorherigen Beispiel veranschaulicht.
Der Konstruktor sollte möglichst wenig Aktionen ausführen. Die wesentliche Aufgabe von Konstruktoren besteht im Erfassen der Konstruktorparameter. Jede andere Verarbeitung sollte erst erfolgen, wenn sie erforderlich ist.
Lösen Sie ggf. Ausnahmen von Instanzkonstruktoren aus.
Konstruktoren sollten Ausnahmen wie jede Methode auslösen und behandeln. Insbesondere sollte ein Konstruktor keine Ausnahmen abfangen und verbergen, die er nicht behandeln kann. Weitere Informationen über Ausnahmen finden Sie unter Entwurfsrichtlinien für Ausnahmen.
Deklarieren Sie den öffentlichen Standardkonstruktor in Klassen explizit, sofern ein solcher Konstruktor erforderlich ist.
Die empfohlene Vorgehensweise ist das explizite Definieren eines Standardkonstruktors, wenn die Klasse dies unterstützt. Obwohl einige Compiler der Klasse automatisch einen Standardkonstruktor hinzufügen, wird die Codeverwaltung durch das explizite Hinzufügen des Standardkonstruktors vereinfacht. Hierdurch wird außerdem sichergestellt, dass der Standardkonstruktor definiert bleibt, selbst wenn er vom Compiler nicht mehr ausgegeben wird, weil Sie einen Konstruktor hinzufügen, der Parameter akzeptiert.
Vermeiden Sie Standardkonstruktoren für Strukturen.
Viele Compiler, z. B. der C#-Compiler, unterstützen keine parameterlosen Konstruktoren für Strukturen.
Rufen Sie in den Konstruktoren keine virtuellen Member für ein Objekt auf.
Der Aufruf eines virtuellen Members bewirkt, dass die Überschreibung mit den meisten Ableitungen aufgerufen wird, unabhängig davon, ob der Konstruktor für den Typ aufgerufen wurde, der die Überschreibung mit den meisten Ableitungen definiert. Dieses Problem wird im folgenden Codebeispiel veranschaulicht. Bei der Ausführung des Basisklassenkonstruktors ruft dieser den Member der abgeleiteten Klasse auf, obwohl der Konstruktor der abgeleiteten Klasse nicht aufgerufen wurde. In diesem Beispiel wird BadBaseClass ausgegeben, um zu zeigen, dass das state-Feld nicht vom DerivedFromBad-Konstruktor aktualisiert wurde.
Imports System
Namespace Examples.DesignGuidelines.MemberDesign
Public Class BadBaseClass
Protected state as String
Public Sub New()
state = "BadBaseClass"
SetState()
End Sub
Public Overridable Sub SetState()
End Sub
End Class
Public Class DerivedFromBad
Inherits BadBaseClass
Public Sub New()
state = "DerivedFromBad "
End Sub
Public Overrides Sub SetState()
Console.WriteLine(state)
End Sub
End Class
Public Class tester
Public Shared Sub Main()
Dim b as DerivedFromBad = new DerivedFromBad()
End Sub
End Class
End Namespace
using System;
namespace Examples.DesignGuidelines.MemberDesign
{
public class BadBaseClass
{
protected string state;
public BadBaseClass()
{
state = "BadBaseClass";
SetState();
}
public virtual void SetState()
{
}
}
public class DerivedFromBad : BadBaseClass
{
public DerivedFromBad()
{
state = "DerivedFromBad ";
}
public override void SetState()
{
Console.WriteLine(state);
}
}
public class tester
{
public static void Main()
{
DerivedFromBad b = new DerivedFromBad();
}
}
}
using namespace System;
namespace Examples { namespace DesignGuidelines { namespace MemberDesign
{
public ref class BadBaseClass
{
protected:
String^ state;
public:
BadBaseClass()
{
state = "BadBaseClass";
SetState();
}
virtual void SetState()
{
}
};
public ref class DerivedFromBad : public BadBaseClass
{
public:
DerivedFromBad()
{
state = "DerivedFromBad ";
}
virtual void SetState() override
{
Console::WriteLine(state);
}
};
public ref class tester
{
public:
static void Main()
{
DerivedFromBad^ b = gcnew DerivedFromBad();
}
};
}}}
Copyright für einzelne Teile 2005 Microsoft Corporation. Alle Rechte vorbehalten.
Copyright für einzelne Teile Addison-Wesley Corporation. Alle Rechte vorbehalten.
Weitere Informationen zu Entwurfsrichtlinien finden Sie unter „Framework-Entwurfs-Richtlinien: Idiome, Konventionen und Muster für wiederverwendbare .NET-Bibliotheken von Krzysztof Cwalina“ book und Brad Abrams, veröffentlicht von Addison-Wesley, 2005.