C# - Conceitos básicos - Classes Estáticas


Hoje vamos falar um pouco sobre classes estáticas usadas na linguagem C#.

Você já deve saber que a linguagem C# é baseada no paradigma da programação orientada a objetos.

Uma classe é um modelo ou gabarito para a definição de objetos.

Então um objeto não existe sem a definição de uma classe.

Através da definição de uma classe, podemos descrever:

A classe seria então o modelo a partir do qual criamos os objetos da classe e fazemos isso criando instâncias da classe.

Criar um objeto de uma classe significa criar uma instância da classe.

Na linguagem C# para criar uma instância de uma classe usamos a palavra-chave new.

Assim o exemplo : Clientes macoratti = new Clientes();

Cria uma instância da classe Cliente() ou seja cria o objeto macoratti do tipo Cliente().

Nos criamos uma instância de uma classe usando a palavra new para podermos definir/utilizar as propriedades/atributos e comportamento do objeto.

Bem, parece que pela exposto acima fica óbvio que você deve criar uma instância da classe (criar um objeto) para poder ter acesso as propriedades e métodos da classe.

Mas não é bem assim.

Você pode acessar uma classe sem criar uma instância desta classe.

Para provar isso vou mostrar um pequeno programa feito em C#:

using System;

namespace Macoratti
{
    class Program
    {
        static void Main(string[] args)
        {
           
            double resultado =
Math.Pow(2,3);
            Console.WriteLine("Dois eleveado ao cubo é igual a : " + resultado.ToString());
            Console.ReadKey();
        }
    }
}

Observe a linha de código que calcula a potência de um número: Math.Pow(2,3)

Aqui temos que o método Pow da classe Math recebe dois argumentos e eleva o primeiro a potência do segundo.

Agora eu pergunto onde esta a instância da classe Math ?

Percebeu que estamos usando um método da classe em criar uma instância da mesma ??

Vamos espiar então o código desta tal classe Math ...

Observe que a classe possui um modificador definido como static e os métodos também possuem o modificador static.

A palavra chave static faz com que os métodos da classe Math estejam associados a classe e não com uma instância particular da classe.

Eles ses tornam acessíveis a partir da classe pois não precisam ser acessados através de uma instância da classe. Embora também possa ser acessado desta forma.

Com isto concluímos que membros declarados como static são membros da classe e não membros de instância.

Logo podemos acessar membros declarados como static em uma classe sem criar uma instância da classe.

Nota: O equivalente em Visual Basic seria a palavra chave shared.

Se tentarmos criar uma instância de uma classe declarada como estática iremos obter o seguinte erro:

Algumas características das classes estáticas:

1. Uma classe estática não pode ser instanciada;
2. Classe estática podem ter somente membros estáticos;
3. Um Membro estático da classe pode ser acessado pelo próprio nome da classe;
4. Uma Classe estática é sealed. Dessa forma uma classe estática não pode ser herdada;
5. Uma Classe estática contém apenas os construtores estáticos;
6. Uma Classe estática não pode ter construtores de instância;
7. Uma Classe estática só pode ser herdada a partir de objetos da classe;
8. Uma Classe estática possui a palavra-chave static como modificador;
9. Os Construtores estáticos da classe estática são chamados apenas uma vez;
10. Uma Classe estática possui somente construtores privados;

Como a plataforma .NET (leia-se CLR) trata uma classe estática ?

As informações da classe estática são carregadas pelo CLR, quando o programa que acessa ou referencia a classe estática esta sendo carregado.
O programa que referência a classe estática não tem controle para especificar quando a classe estática deve ser carregado pelo CLR
A classe estática permanece na memória pelo período de vida do domínio de aplicação no qual os programas residem.

Como podemos criar uma classe estática na linguagem C# ?

1- Crie uma nova classe usando a palavra-chave static;
2- Crie um construtor privado na classe estática;
3- Faça com que todos os membros da classe seja do tipo static;

Exemplo prático:

Abra o Visual C# 2010 Express Edition (ou o SharpDevelop 4) e no menu FIle selecione New Project selecionando o template Console Application com o nome ClassesEstaticas;

A seguir no menu Project -> Add Class selecione o template Class e informe o nome Calculadora.cs e clique em OK;

A seguir defina o seguinte código na classe Calculadora:

namespace Macoratti
{
    public static class Calculadora
    {
        public static int Somar(int numero1, int numero2)
        {
            return numero1 + numero2;
        }

        public static int Subtrair(int numero1, int numero2)
        {
            return numero1 - numero2;
        }
        public static int Multiplicar(int numero1, int numero2)
        {
            return numero1 * numero2;
        }
        public static int Dividir(int numero1, int numero2)
        {
            return numero1 / numero2;
        }
    }
}
Nesta classe temos definido 4 métodos:
  1. Somar(int numero1, int numero2)
  2. Subtrair(int numero1, int numero2)
  3. Multiplicar(int numero1, int numero2)
  4. Dividir(int numero1, int numero2)

Observe que tanto a classe como os métodos usam o modificador static.

Concluímos assim que a nossa classe Calculadora e uma classe estática
e portanto não precisamos criar uma instância dessa classe para usar os
seus métodos.

Vamos usar a nossa classe Calculadora e verificar qual o seu comportamento...

using System;

namespace Macoratti
{
    class Program
    {
        static void Main(string[] args)
        {

            Console.WriteLine("Soma= " + Calculadora.Somar(7, 2).ToString());
           
            Console.WriteLine("Subtração  = " + Calculadora.Subtrair(7, 2).ToString());

            int resultado = Calculadora.Multiplicar(7, 2);
           
            Console.WriteLine("Multiplicação  = " + resultado);
           
            Console.WriteLine("Divisão = " + Calculadora.Dividir(7, 2).ToString());
           
            Console.Read(); 
        }
    }
}

Executando o projeto iremos obter:

Considerações finais

Como vimos Static/Shared é um recurso disponível tanto na linguagem C# como na linguagem Visual Basic e sua utilização quando bem feita é válida.

Mas você deve ter em mente que usar o recurso static/shared de forma indiscriminada além de violar o paradigma a orientação a objetos pode te dar muita dor de cabeça.

Um método estático indica que na verdade não sabe a quem pertence, como ele não é um método de instância, ele não precisa da instância da classe para ser usado, então, a rigor, ele fica meio à vontade usando a assinatura da classe e não usa o estado interno da classe.

Se você lembrar do princípio da responsabilidade (SRP) que dita que uma classe deve ter uma única responsabilidade um método estático estaria violando este princípio pois ele tende a ter uma responsabilidade que não é a mesma da classe à qual esta vinculado.

Outro problema é que essencialmente um método estático pode ser chamado por qualquer um a partir de qualquer lugar da sua aplicação, além disso o método estático pretende ser parte de uma classe quando na verdade a classe é usada pelo método estático como um ponto de apoio. Com base nisso os métodos estáticos estão mais voltados para a programação procedural do que para a orientação a objetos.

Então quando eu deveria usar o recurso static/shared em minhas aplicações ?

Vou dar dois exemplos de utilização que considero válidos:

  1. Declaração de constantes globais como o número PI. Veja que eu disse constantes globais e não variáveis globais;
  2. Criação de objetos - principalmente em métodos sobrecarregados onde podemos usar um construtor estático para ficar mais claro como o objeto esta sendo criado;

public static EnviaEmail ComAnexos(string destino, string conteúdo); X public void enviaEmail(string destino, string conteudo);
public static EnviaEmail SemAnexos(string destino); X public void EnviaEmail(string destino);

EnviaEmail envemail = new EnviaEmail("teste@teste.com"); X EnviaEmail envemail = EnviaEmail.SemAnexos(teste@teste.com");

Bem, é claro que eu não esgotei o assunto e volto a repetir o dito popular que "bom senso e canja de galinha não fazem mal a ninguém..."

Rom 5:18 Portanto, assim como por uma só ofensa veio o juízo sobre todos os homens para condenação, assim também por um só ato de justiça veio a graça sobre todos os homens para justificação e vida.
Rom 5:19
Porque, assim como pela desobediência de um só homem muitos foram constituídos pecadores, assim também pela obediência de um muitos serão constituídos justos.

Rom 5:20
Sobreveio, porém, a lei para que a ofensa abundasse; mas, onde o pecado abundou, superabundou a graça;

Referências:

José Carlos Macoratti