Quando usar classs estáticas em c #

Aqui está o que o MSDN tem a dizer em Quando usar classs estáticas :

static class CompanyInfo { public static string GetCompanyName() { return "CompanyName"; } public static string GetCompanyAddress() { return "CompanyAddress"; } //... } 

Use uma class estática como uma unidade de organização para methods não associados a objects específicos. Além disso, uma class estática pode tornar sua implementação mais simples e rápida, pois você não precisa criar um object para chamar seus methods. É útil organizar os methods dentro da class de maneira significativa, como os methods da class Math no namespace System.

Para mim, esse exemplo não parece cobrir muitos cenários de uso possíveis para classs estáticas. No passado eu usei classs estáticas para conjuntos sem estado de funções relacionadas, mas é sobre isso. Então, em que circunstâncias deve (e não deveria) uma class ser declarada estática?

Escrevi meus pensamentos sobre classs estáticas em uma resposta anterior do Stack Overflow: Class with single method – melhor abordagem?

Eu costumava amar classs utilitárias cheias de methods estáticos. Eles fizeram uma grande consolidação de methods auxiliares que, de outra forma, estariam por aí causando um inferno de redundância e manutenção. Eles são muito fáceis de usar, sem instanciação, sem descarte, apenas fogo e esquecimento. Eu acho que esta foi a minha primeira tentativa inconsciente de criar uma arquitetura orientada a serviços – muitos serviços sem estado que apenas fizeram seu trabalho e nada mais. Como um sistema cresce no entanto, os dragões estão chegando.

Polimorfismo

Digamos que temos o método UtilityClass.SomeMethod que vibra alegremente. De repente, precisamos mudar um pouco a funcionalidade. A maior parte da funcionalidade é a mesma, mas temos que alterar algumas partes, no entanto. Se não fosse um método estático, poderíamos criar uma class derivada e alterar o conteúdo do método conforme necessário. Como é um método estático, não podemos. Claro, se precisarmos apenas adicionar funcionalidade antes ou depois do método antigo, podemos criar uma nova class e chamar a antiga dentro dela – mas isso é nojento.

Problemas de interface

Métodos estáticos não podem ser definidos por meio de interfaces por motivos lógicos. E como não podemos replace methods estáticos, as classs estáticas são inúteis quando precisamos passá-las pela interface. Isso nos torna incapazes de usar classs estáticas como parte de um padrão de estratégia. Podemos corrigir alguns problemas passando delegates em vez de interfaces .

Testando

Isso basicamente anda de mãos dadas com as dificuldades de interface mencionadas acima. Como nossa capacidade de intercambiar implementações é muito limitada, também teremos problemas para replace o código de produção pelo código de teste. Mais uma vez, podemos envolvê-los, mas isso exigirá que alteremos grandes partes do nosso código apenas para aceitar invólucros em vez dos objects reais.

Foster blobs

Como os methods estáticos são normalmente usados ​​como methods utilitários e os methods utilitários normalmente terão propósitos diferentes, nós rapidamente acabaremos com uma class grande preenchida com funcionalidade não-coerente – idealmente, cada class deve ter uma única finalidade dentro do sistema. Eu prefiro ter cinco vezes as aulas, desde que seus objectives sejam bem definidos.

Parameter creep

Para começar, esse pequeno e inocente método estático pode ter um único parâmetro. À medida que a funcionalidade cresce, alguns novos parâmetros são adicionados. Em breve outros parâmetros são adicionados, que são opcionais, portanto, criamos sobrecargas do método (ou apenas adicionamos valores padrão, em idiomas que os suportam). Em pouco tempo, temos um método que leva 10 parâmetros. Apenas os três primeiros são realmente necessários, os parâmetros 4-7 são opcionais. Mas se o parâmetro 6 for especificado, é necessário preencher 7-9 também … Se tivéssemos criado uma class com o único objective de fazer o que esse método estático fazia, poderíamos resolver isso observando os parâmetros necessários no construtor e permitindo que o usuário defina valores opcionais por meio de propriedades ou methods para definir vários valores interdependentes ao mesmo tempo. Além disso, se um método tiver atingido essa complexidade, provavelmente ele precisará estar em sua própria class.

Consumidores exigentes para criar uma instância de classs sem motivo

Um dos argumentos mais comuns é: Por que exigir que os consumidores de nossa class criem uma instância para invocar esse método único, sem ter mais uso para a instância depois? Criar uma instância de uma class é uma operação muito barata na maioria das linguagens, portanto a velocidade não é um problema. Adicionar uma linha extra de código ao consumidor é um custo baixo para estabelecer a base de uma solução muito mais sustentável no futuro. E, finalmente, se você quiser evitar a criação de instâncias, basta criar um wrapper singleton de sua class que permita uma fácil reutilização – embora isso faça com que o requisito de que sua class seja stateless. Se não for stateless, você ainda pode criar methods wrapper estáticos que lidam com tudo, enquanto ainda oferece todos os benefícios a longo prazo. Finalmente, você também pode criar uma class que oculte a instanciação como se fosse um singleton: MyWrapper.Instance é uma propriedade que retorna apenas new MyClass();

Apenas um Sith lida em absolutos

Claro, há exceções para o meu desagrado de methods estáticos. Classes de utilitários verdadeiras que não representam risco para inchar são casos excelentes para methods estáticos – System.Convert como um exemplo. Se o seu projeto é único, sem requisitos para manutenção futura, a arquitetura geral realmente não é muito importante – estática ou não estática, realmente não importa -, entretanto, a velocidade de desenvolvimento.

Padrões, padrões e padrões!

O uso de methods de instância não inibe você de usar methods estáticos e vice-versa. Contanto que haja um raciocínio por trás da diferenciação e seja padronizado. Não há nada pior do que investigar uma camada de negócios alastrando com diferentes methods de implementação.

Ao decidir se deve tornar uma class estática ou não-estática, é necessário verificar quais informações você está tentando representar. Isso implica em um estilo de programação mais “de baixo para cima “, em que você se concentra nos dados que está representando primeiro. A turma está escrevendo um object do mundo real como uma rocha ou uma cadeira? Essas coisas são físicas e têm atributos físicos, como cor, peso, que informam que você pode instanciar vários objects com propriedades diferentes. Eu posso querer uma cadeira preta e uma cadeira vermelha ao mesmo tempo. Se você precisar de duas configurações ao mesmo tempo, saberá instantaneamente que deseja instanciá-la como um object, para que cada object possa ser único e existir ao mesmo tempo.

Por outro lado, as funções estáticas tendem a emprestar mais para ações que não pertencem a um object do mundo real ou a um object que você pode representar facilmente. Lembre-se de que os predecessores do C # são C ++ e C, onde você pode definir funções globais que não existem em uma class. Isso empresta mais a programação ‘de cima para baixo ‘. Métodos estáticos podem ser usados ​​para esses casos em que não faz sentido que um ‘object’ execute a tarefa. Ao forçar você a usar as classs, isso facilita o agrupamento da funcionalidade relacionada, o que ajuda a criar um código mais sustentável.

A maioria das classs pode ser representada por estática ou não-estática, mas quando você estiver em dúvida, volte para suas raízes de OOP e tente pensar sobre o que está representando. É um object que está executando uma ação (um carro que pode acelerar, desacelerar, girar) ou algo mais abstrato (como exibir a saída).

Entre em contato com sua OOP interior e você nunca poderá errar!

Para o C # 3.0, os methods de extensão podem existir apenas em classs estáticas de nível superior.

Se você usar ferramentas de análise de código (por exemplo, FxCop ), ele recomendará que você marque um método static se esse método não acessar os dados da instância. A lógica é que há um ganho de desempenho. MSDN: CA1822 – Marcar membros como estáticos .

É mais uma diretriz do que uma regra, realmente …

Eu costumo usar classs estáticas para fábricas. Por exemplo, esta é a class de registro em um dos meus projetos:

 public static class Log { private static readonly ILoggerFactory _loggerFactory = IoC.Resolve(); public static ILogger For(T instance) { return For(typeof(T)); } public static ILogger For(Type type) { return _loggerFactory.GetLoggerFor(type); } } 

Você pode até ter notado que o IoC é chamado com um acessador estático. Na maioria das vezes, para mim, se você pode chamar methods estáticos em uma class, isso é tudo que você pode fazer, então marquei a class como estática para maior clareza.

Comecei a usar classs estáticas quando desejo usar funções, em vez de classs, como minha unidade de reutilização. Anteriormente, eu era todo sobre o mal das classs estáticas. No entanto, aprendendo F # fez-me vê-los sob uma nova luz.

O que quero dizer com isso? Bem, digamos, ao trabalhar com algum código super DRY , acabo com um monte de classs de um método. Eu só posso puxar esses methods em uma class estática e, em seguida, injetá-los em dependencies usando um delegado. Isso também funciona muito bem com o meu recipiente de injeção de dependência (DI) de escolha Autofac.

Claro que assumir uma dependência direta de um método estático ainda é geralmente mal (existem alguns usos não-maus).

Eu uso classs estáticas como um meio de definir “funcionalidade extra” que um object de um determinado tipo poderia usar em um contexto específico. Normalmente, eles acabam sendo classs de utilidade.

Além disso, acho que “Use uma class estática como uma unidade de organização para methods não associados a objects específicos”. descrever bem o uso pretendido.

As classs estáticas são muito úteis e têm um lugar, por exemplo, bibliotecas.

O melhor exemplo que posso fornecer é a class .Net Math, uma class estática do namespace do sistema que contém uma biblioteca de funções matemáticas.

É como qualquer outra coisa, use a ferramenta certa para o trabalho e, se não, qualquer coisa pode ser abusada.

Em branco, descartar classs estáticas como erradas, não usá-las, ou dizer “pode ​​haver apenas uma” ou nenhuma, é tão errado quanto usá-las.

C # .Net contém um número de classs estáticas que é usado apenas como a class matemática.

Então, dada a implementação correta, eles são tremendamente úteis.

Temos uma class TimeZone estática que contém várias funções de fuso horário relacionadas a negócios, não há necessidade de criar várias instâncias da class de modo semelhante à class Math que contém um conjunto de funções realeadas (methods) TimeZone acessíveis globalmente em uma class estática .

Esta é outra pergunta antiga, mas muito calorosa, desde que a POO entrou em cena. Há muitas razões para usar (ou não) uma aula estática, é claro, e a maioria delas foi abordada na multiplicidade de respostas.

Vou apenas adicionar meus 2 centavos a isso, dizendo que, eu faço uma class estática, quando esta class é algo que seria único no sistema e que realmente não faria sentido ter qualquer instância dele no programa. No entanto, reservo esse uso para turmas grandes. Eu nunca declarar essas classs pequenas como no exemplo do MSDN como “estático” e, certamente, não classs que serão membros de outras classs.

Também gosto de observar que methods estáticos e classs estáticas são duas coisas diferentes a considerar. As principais desvantagens mencionadas na resposta aceita são para methods estáticos. As classs estáticas oferecem a mesma flexibilidade que as classs normais (onde propriedades e parâmetros estão em questão), e todos os methods usados ​​nelas devem ser relevantes para o propósito da existência da class.

Um bom exemplo, na minha opinião, de um candidato para uma class estática é uma class “FileProcessing”, que conteria todos os methods e propriedades relevantes para os vários objects do programa para executar operações complexas de FileProcessing. Dificilmente tem qualquer significado ter mais de uma instância dessa class e ser estático a tornará prontamente disponível para tudo no seu programa.

Eu só uso classs estáticas para methods auxiliares, mas com o advento do C # 3.0, eu prefiro usar methods de extensão para esses.

Eu raramente uso methods de classs estáticas pelas mesmas razões pelas quais eu raramente uso o “padrão de design” singleton.

Baseado no MSDN :

  1. Você não pode criar a instância para classs estáticas
  2. Se a class declarada como estática, a variável de membro deve ser estática para essa class
  3. Selado [não pode ser herdado]
  4. Não é possível conter o construtor de instância
  5. Gerenciamento de Memória

Exemplo: cálculos matemáticos (valores matemáticos) não mudam [CÁLCULO PADRÃO PARA VALORES DEFINIDOS]