Compartilhar via


Design do construtor

Construtores são usados para inicializar a tipos e criar instâncias de tipos de métodos especiais. Um construtor de tipo é usado para inicializar dados estáticos em um tipo. Um construtor de tipo é chamado pelo common language runtime (CLR) antes de quaisquer instâncias do tipo são criadas. Construtores de tipo são static (Shared em Visual Basic) e não podem receber parâmetros. O construtor de instância é usado para criar instâncias de um tipo. Construtores de instância podem levar a parâmetros, mas não são necessários para fazer isso. 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 simple 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áticos em vez de um construtor a semântica da operação desejada não mapeiam diretamente para a construção de uma nova instância, ou se seguindo as diretrizes de design do construtor perceber artificial.

Use os parâmetros do construtor como atalhos para definir as propriedades principais.

Definindo propriedades usando o construtor deve ser idêntico ao definir as propriedades diretamente. O seguinte código exemplo mostra um EmployeeRecord classe pode ser inicializado, chamando um construtor ou definindo as propriedades diretamente. O EmployeeManagerConstructor classe demonstra inicializando um EmployeeRecord objeto usando o construtor. O EmployeeManagerProperties classe demonstra inicializando um EmployeeRecord usando o objeto de propriedades. O Tester classe demonstra que 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);
        }
    }
}
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);
        }
    };
}}}

Observe que esses exemplos e em uma biblioteca bem projetada, ambas as abordagens criam objetos no mesmo estado. Não importa qual abordagem que um desenvolvedor que prefere usar.

Use o mesmo nome para os parâmetros do construtor e uma propriedade, se os parâmetros do construtor são usados para simplesmente definir a propriedade. A única diferença entre esses parâmetros e as propriedades deve ser casing.

Essa diretriz é ilustrado no exemplo anterior.

Fazer o 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 outro processamento deve ser atrasado até que o necessário.

Lança exceções de construtores de instância, se apropriado.

Construtores devem lançar e manipular exceções como qualquer método. Especificamente, um construtor não deve capturar e ocultar todas as exceções que ele não pode tratar. Para obter informações adicionais sobre exceções, consulte Diretrizes de design para exceções.

Declare explicitamente o construtor padrão público em classes, se tal um construtor é necessário.

É uma prática recomendada para definir explicitamente um construtor padrão, se sua classe oferece suporte a ele. Embora alguns compiladores adicionam automaticamente um construtor padrão à sua classe, adicioná-lo explicitamente facilita a manutenção de código. Ele também garante que o construtor padrão permanece definido, mesmo se o compilador pára a emissão de porque você adicionar um construtor que aceita parâmetros.

Evite ter construtores padrão nas estruturas.

Muitos compiladores, incluindo o compilador C#, não oferecem suporte a construtores sem parâmetros nas estruturas.

Não chamam membros virtuais em um objeto dentro de seus construtores.

Chamar um membro virtual faz com que a substituição de derivados de mais ser chamado independentemente, por exemplo, se o construtor para o tipo que define a substituição de derivados de maioria foi chamado. O exemplo de código a seguir demonstra esse problema. Como o construtor de 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 estado não foi 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();
        }
    }
}
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();
        }
    };
}}}

Portions Copyright 2005 Microsoft Corporation. Todos os direitos reservados.

Portions Copyright Addison-Wesley Corporation. Todos os direitos reservados.

Para obter mais informações sobre as diretrizes de design, consulte a "diretrizes de Design do Framework: Convenções, idiomas e padrões de reutilizável.Bibliotecas de rede" catálogo por Krzysztof Cwalina e Brad Abrams, publicado pela Addison-Wesley, 2005.

Consulte também

Conceitos

Design do construtor de tipo

Outros recursos

Diretrizes de Design do membro

Diretrizes de Design para desenvolvimento bibliotecas de classe