Curiosidades C# – Construtores estáticos

Tipicamente um construtor é usado para definir o valor dos dados no momento da criação de um objeto. No entanto, o que acontece se você tentar atribuir o valor estático em um construtor padrão? Você vai descobrir que o valor é redefinido toda vez que você cria um novo objeto.

Exemplo:

using System;
namespace StaticConstructors
{
    class Program
    {
        static void Main(string[] args)
        {
            var t1 = new Theater(5);
            Console.WriteLine("Obj 1 | Price: " + t1.GetTicketPrice() + " - Number of: " + t1.NumberOfTickets);
            t1.SetTicketPrice(543.21); // => Change the price of the ticket
            Console.WriteLine("Obj 1 | Price: " + t1.GetTicketPrice() + " - Number of: " + t1.NumberOfTickets);

            var t2 = new Theater(9); // => create a new instance
            // => both instaces now have the same ticket price
            Console.WriteLine("Obj 1 | Price: " + t1.GetTicketPrice() + " - Number of: " + t1.NumberOfTickets);
            Console.WriteLine("Obj 2 | Price: " + t2.GetTicketPrice() + " - Number of: " + t2.NumberOfTickets);
        }
    }

    public class Theater
    {
        public static double TicketPrice { get; set; }
        public int NumberOfTickets { get; set; }

        public Theater(int numberOfTickets)
        {
            NumberOfTickets = numberOfTickets;
            TicketPrice = 123.45;
        }

        public double GetTicketPrice()
        {
            return TicketPrice;
        }

        public void SetTicketPrice(double ticketPrice)
        {
            TicketPrice = ticketPrice;
        }
    }
}
/* This will print
Obj 1 | Price: 123,45 - Number of: 5
Obj 1 | Price: 543,21 - Number of: 5
Obj 1 | Price: 123,45 - Number of: 5
Obj 2 | Price: 123,45 - Number of: 9
 */

Todas as vezes que criamos uma instância o valor estático reiniciado e isso afeta todos os objetos existentes.

Para evitar esse problema podemos fazer uso de construtores estáticos

Construtores estáticos

Um construtor estático é usado para inicializar quaisquer dados estáticos ou para executar uma ação específica que precisa ser executada apenas uma vez. Ele é chamado automaticamente antes que a primeira instância seja criada ou que quaisquer membros estáticos sejam referenciados.

No exemplo acima, não queremos que o valor estático seja reiniciado a cada instância criada, e por este motivo podemos usar o construtor estático.

Exemplo:

using System;
namespace StaticConstructors
{
    class Program
    {
        static void Main(string[] args)
        {
            var t1 = new Theater(5);
            Console.WriteLine("Obj 1 | Price: " + t1.GetTicketPrice() + " - Number of: " + t1.NumberOfTickets);
            t1.SetTicketPrice(543.21); // => Change the price of the ticket
            Console.WriteLine("Obj 1 | Price: " + t1.GetTicketPrice() + " - Number of: " + t1.NumberOfTickets);

            var t2 = new Theater(9); // => create a new instance
            // => both instaces now have the same ticket price
            Console.WriteLine("Obj 1 | Price: " + t1.GetTicketPrice() + " - Number of: " + t1.NumberOfTickets);
            Console.WriteLine("Obj 2 | Price: " + t2.GetTicketPrice() + " - Number of: " + t2.NumberOfTickets);
        }
    }

    class Theater
    {
        public static double TicketPrice;
        public int NumberOfTickets { get; set; }

        public Theater(int numberOfTickets)
        {
            NumberOfTickets = numberOfTickets;
        }

        static Theater()
        {
            Console.WriteLine("static Theater - This run only one time");
            TicketPrice = 123.45;
        }

        public double GetTicketPrice()
        {
            return TicketPrice;
        }

        public void SetTicketPrice(double ticketPrice)
        {
            TicketPrice = ticketPrice;
        }
    }
}
/* This will print
static Theater - This run only one time
Obj 1 | Price: 123,45 - Number of: 5
Obj 1 | Price: 543,21 - Number of: 5
Obj 1 | Price: 543,21 - Number of: 5
Obj 2 | Price: 543,21 - Number of: 9
 */

Dada essa modificação, quando você cria novos objetos Theater, o valor dos dados estáticos é preservado, como o membro estático (TicketPrice) é definido apenas uma vez no construtor estático, independentemente do número de objetos criados.

Notas:
– Uma classe ou struct só pode ter um construtor estático.
– Os construtores estáticos não podem ser herdados ou sobrecarregados.
– Um construtor estático executa exatamente uma vez, independentemente de quantos objetos do tipo são criados.
– O construtor estático é acionado quando cria a primeira instância da classe ou antes de acessar o primeiro membro estático.
– O construtor estático é executado antes de qualquer construtor no nível da instância.
– Se você não fornecer um construtor estático para inicializar campos estáticos, todos os campos estáticos serão inicializados para o valor padrão.

Qualquer dúvida ou dicas, entre em contato: leandrolt@gmail.com

Principais referências

– Livro: Pro C# 7: With .NET and .NET Core – Andrew Troelsen
– https://docs.microsoft.com/pt-br/dotnet/csharp/programming-guide/classes-and-structs/static-constructors

Leave a Reply

Your email address will not be published. Required fields are marked *