Design do construtor
Construtores são métodos especiais usados para inicializar tipos e criar instâncias de tipos. Um construtor de tipo é usado para inicializar dados estático em um tipo. Um construtor de tipo é chamado pelo common linguagem tempo de execução (CLR) antes que quaisquer instâncias do tipo sejam criadas. Construtores de tipo são static (Shared no Visual Basic) e não pode levar a parâmetros. Um construtor de instância é usado para criar instâncias de um tipo. Construtores de instância podem levar parâmetros, mas não serão necessário fazê-lo. Um construtor de instância sem parâmetros é chamado de um construtor padrão.
As diretrizes a seguir descrevem as práticas recomendadas para a criação de construtores.
Considere fornecer simples, idealmente padrão, construtores.Um construtor simples tem um número muito pequeno de parâmetros, e todos os parâmetros são tipos primitivos ou enumerações.
Considere o uso de um método de fábrica estática em vez de um construtor se a semântica da operação desejada não mapear diretamente para a construção de uma nova instância ou se perceber anormais seguindo as diretrizes de design do construtor.
Usar parâmetros do construtor sistema autônomo atalhos para configuração propriedades principais.
Definindo propriedades usando o construtor deve ser idêntico a definir as propriedades diretamente. O exemplo de código a seguir mostra um EmployeeRecord classe que pode ser inicializado chamando um construtor ou definindo propriedades diretamente. The EmployeeManagerConstructor classe demonstra inicializando um EmployeeRecord usando o construtor de objeto. The EmployeeManagerProperties classe demonstra inicializando um EmployeeRecord usando propriedades de objeto. The Tester classe demonstra independentemente da técnica usada, os objetos têm o mesmo estado.
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);
}
}
}
Observe que esses exemplos e, em uma biblioteca bem projetada, ambas as abordagens criar objetos no mesmo estado. Não importa qual abordagem desenvolvedor prefere usar.
Use o mesmo nome para parâmetros do construtor e uma propriedade, se os parâmetros do construtor são usados para simplesmente conjunto a propriedade.A única diferença entre esses parâmetros e as propriedades deve ser casing.
Essa diretriz é ilustrado no exemplo anterior.
Fazer um mínimo de trabalho no construtor.Construtores não devem fazer muito trabalho diferente para capturar os parâmetros do construtor.O custo de qualquer Outros processamento deve ser atrasado até que o necessário.
Lançar exceções de construtores de instância, se apropriado.
Construtores devem gerar e manipular exceções como qualquer método. Especificamente, um construtor não deve capturar e ocultar todas as exceções que não pode manipular. Para obter informações adicionais em exceções, consulte Diretrizes de design para exceções.
Declare explicitamente o construtor padrão público em classes, se tal um construtor for necessário.
É uma prática melhor definir explicitamente um construtor padrão se sua classe for compatível. Embora alguns compiladores adicionar automaticamente um construtor padrão à sua classe, adicioná-lo explicitamente faz manutenção de código mais fácil. Ele também garante que o construtor padrão permanece definido, mesmo que o compilador pára emitindo-lo como adicionar um construtor com parâmetros.
Evite construtores padrão nas estruturas.
Muitos compiladores, incluindo o compilador translation from VPE for Csharp, não oferecem suporte a construtores sem parâmetros em estruturas.
Não chame membros virtual em um objeto dentro de seus construtores.
Chamar um membro virtual faz com que a substituir mais derivado deve ser chamado independentemente se o construtor para o tipo que define a substituir mais derivado foi chamado. O exemplo de código a seguir demonstra esse problema. sistema autônomo o construtor da classe base é executado, ele chama o membro de classe derivada, mesmo que o construtor de classe derivada não foi chamado. Este exemplo imprime BadBaseClass para mostrar o campo de estado não tiver sido atualizado pela DerivedFromBad construtor.
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();
}
}
}
Partes direitos autorais 2005 Microsoft Corporation. Todos os direitos reservados.
Partes direitos autorais Addison-Wesley Corporation. Todos os direitos reservados.
Para obter mais informações sobre diretrizes de design, consulte a "diretrizes de design do estrutura: Catálogo de convenções, idiomas e padrões para bibliotecas do .NET reutilizável"Krzysztof Cwalina e Brad Abrams, publicado pela Addison-Wesley, 2005.
Consulte também
Conceitos
Outros recursos
Diretrizes de design de membro
Diretrizes de Design para desenvolvimento bibliotecas de classe