Os métodos C # que podem ser estáticos devem ser estáticos?
Estávamos discutindo isso hoje e estou meio em cima do muro. Imagine que você tem um método longo do qual refatora algumas linhas. O novo método provavelmente pega algumas variáveis locais do método pai e retorna um valor. Isso significa que pode ser estático.
A questão é: deve ser estático? Não é estático por design ou escolha, simplesmente por sua natureza, pois não faz referência a nenhum valor de instância.
Respostas:
Depende. Na verdade, existem 2 tipos de métodos estáticos:
Em uma base de código de tamanho pequeno a médio, você pode realmente tratar os dois métodos de forma intercambiável.
Se você tem um método que está na primeira categoria (pode ser estático) e precisa alterá-lo para acessar o estado da classe, é relativamente simples descobrir se é possível transformar o método estático em um método de instância.
Em uma grande base de código, no entanto, o grande número de sites de chamada pode tornar a pesquisa para ver se é possível converter um método estático em um não estático muito caro. Muitas vezes as pessoas verão o número de ligações e dirão "ok ... é melhor não mudar esse método, mas sim criar um novo que faça o que eu preciso".
Isso pode resultar em:
Essas duas coisas são ruins.
Portanto, meu conselho seria que, se você tiver uma base de código acima de 200K LOC, eu só tornaria os métodos estáticos se eles fossem métodos estáticos obrigatórios.
A refatoração de não estático para estático é relativamente fácil (basta adicionar uma palavra-chave), então se você quiser transformar um pode ser estático em um estático real mais tarde (quando precisar da funcionalidade fora de uma instância), você pode. No entanto, a refatoração inversa, transformando um método can-be-static em um método de instância é MUITO mais caro.
Com grandes bases de código, é melhor errar pelo lado da facilidade de extensão do que pelo lado da pureza idealógica.
Portanto, para grandes projetos, não torne as coisas estáticas, a menos que você precise que elas o sejam. Para pequenos projetos, basta fazer o que você mais gosta.
fonte
Eu não o tornaria um membro público estático dessa classe . O motivo é que torná-lo público estático é dizer algo sobre o tipo da classe: não apenas que "esse tipo sabe como fazer esse comportamento", mas também "é responsabilidade desse tipo realizar esse comportamento". E as probabilidades são de que o comportamento não tenha mais qualquer relação real com o tipo maior.
Isso não significa que eu não o tornaria estático, no entanto. Pergunte a si mesmo: o novo método poderia logicamente pertencer a outro lugar? Se você puder responder "sim" a isso, provavelmente deseja torná-lo estático (e movê-lo também). Mesmo que isso não seja verdade, você ainda pode torná-lo estático. Só não marque
public
.Por uma questão de conveniência, você pode pelo menos marcá-lo
internal
. Isso normalmente evita a necessidade de mover o método se você não tiver acesso fácil a um tipo mais apropriado, mas ainda o deixa acessível onde necessário de uma maneira que não apareça como parte da interface pública para usuários de sua classe .fonte
Não necessariamente.
Mover os métodos públicos de estáticos para não estáticos é uma alteração importante e exigiria alterações para todos os chamadores ou consumidores. Se um método parece ser um método de instância, mas acontece de não usar nenhum membro de instância, eu sugeriria torná-lo um método de instância como uma medida de segurança futura.
fonte
Sim. A razão "pode ser estático" é que não opera no estado do objeto sobre o qual é chamado. Portanto, não é um método de instância, mas um método de classe. Se ele puder fazer o que precisa sem nunca acessar os dados da instância, então deve ser estático.
fonte
Sim, deveria. Existem várias métricas de acoplamento que medem como sua classe depende de outras coisas, como outras classes, métodos, etc. Tornar métodos estáticos é uma maneira de manter o grau de acoplamento baixo, uma vez que você pode ter certeza de que um método estático não faz referência a nenhum membros.
fonte
Acho que ficaria um pouco mais legível se você marcasse como estático ... Então, alguém que aparecer saberia que não faz referência a nenhuma variável de instância sem ter que ler a função inteira ...
fonte
Pessoalmente, sou um grande fã da apatridia. Seu método precisa acessar o estado da classe? Se a resposta for não (e provavelmente não, caso contrário, você não consideraria torná-lo um método estático), então sim, vá em frente.
Nenhum acesso ao estado é menos dor de cabeça. Assim como é uma boa ideia ocultar membros privados que não são necessários para outras classes, é uma boa ideia ocultar o estado dos membros que não precisam dele. Acesso reduzido pode significar menos bugs. Além disso, torna o encadeamento mais fácil, pois é muito mais fácil manter os membros estáticos protegidos contra encadeamentos. Há também uma consideração de desempenho, pois o tempo de execução não precisa passar uma referência a isso como um parâmetro para métodos estáticos.
Obviamente, a desvantagem é que, se você descobrir que seu método anteriormente estático terá que acessar o estado por algum motivo, será necessário alterá-lo. Agora eu entendo que isso pode ser um problema para APIs públicas, portanto, se este for um método público em uma classe pública, talvez você deva pensar um pouco sobre as implicações disso. Ainda assim, nunca enfrentei uma situação no mundo real em que isso realmente causasse um problema, mas talvez eu só tenha sorte.
Então, sim, vá em frente, por todos os meios.
fonte
Métodos estáticos são mais rápidos do que os não estáticos, então sim, eles devem ser estáticos se puderem e não há nenhuma razão especial para deixá-los não estáticos .
fonte
Estou surpreso que tão poucos estejam mencionando o encapsulamento aqui de fato. Um método de instância terá automaticamente acesso a todos os campos, propriedades e métodos privados (instância). Além de todos os protegidos herdados das classes base.
Ao escrever código, você deve escrevê-lo de forma que exponha o mínimo possível e também para que tenha acesso ao mínimo possível.
Então, sim, pode ser importante tornar seu código mais rápido, o que aconteceria se você estivesse tornando seus métodos estáticos, mas geralmente mais importante do que tornar seu código o mais incapaz de criar bugs possível também. Uma maneira de conseguir isso é fazer com que seu código tenha acesso ao mínimo possível de "coisas privadas".
Isso pode parecer irrelevante à primeira vista, pois o OP está obviamente falando sobre refatoração que não pode dar errado neste cenário e criar novos bugs, no entanto, esse código refatorado deve ser mantido no futuro e modificado, o que faz com que seu código tenha um ataque maior " superfície "em relação a novos bugs se ele tiver acesso a membros de instâncias privadas. Portanto, em geral, acho que a conclusão aqui é que "sim, principalmente seus métodos devem ser estáticos", a menos que haja quaisquer outras razões para não tê-los estáticos. E isso simplesmente porque é "melhor uso de encapsulamento e ocultação de dados e cria um código 'mais seguro'" ...
fonte
Tornar algo estático só porque você pode não é uma boa ideia. Os métodos estáticos devem ser estáticos devido ao seu design, não por acaso.
Como Michael disse, alterar isso posteriormente interromperá o código que o está usando.
Dito isso, parece que você está criando uma função de utilidade privada para a classe que é, na verdade, estática por design.
fonte
Se você foi capaz de refatorar algumas linhas e o método resultante pode ser estático, é provavelmente uma indicação de que as linhas que você puxou desse método não pertencem à classe contida, e você deve considerar movê-las para sua própria classe.
fonte
Pessoalmente, eu não teria escolha a não ser torná-lo estático. Neste caso, o Resharper emite um aviso e nosso PM tem uma regra "Sem avisos do Resharper".
fonte
Depende, mas geralmente eu não torno esses métodos estáticos. O código está sempre mudando e talvez um dia eu queira tornar essa função virtual e substituí-la em uma subclasse. Ou talvez algum dia ele precise fazer referência a variáveis de instância. Será mais difícil fazer essas alterações se cada site de chamada tiver que ser alterado.
fonte
Eu sugiro que a melhor maneira de pensar sobre isso é: se você precisa de um método de classe que precise ser chamado quando nenhuma instância da classe for instanciada ou manter algum tipo de estado global, estático é uma boa ideia. Mas, em geral, sugiro que você prefira tornar os membros não estáticos.
fonte
Você deve pensar sobre seus métodos e classes:
Se os dois últimos forem 'sim', então seu método / classe provavelmente deve ser estático.
O exemplo mais usado provavelmente é a
Math
classe. Todas as principais linguagens OO o possuem e todos os métodos são estáticos. Porque você precisa ser capaz de usá-los em qualquer lugar, a qualquer hora, sem criar uma instância.Outro bom exemplo é o
Reverse()
método em C #.Este é um método estático na
Array
classe. Ele inverte a ordem do seu array.Código:
Ele nem retorna nada, seu array é invertido, porque todos os arrays são instâncias da classe Array.
fonte
Contanto que você torne o novo método private static , não é uma alteração significativa. Na verdade, FxCop inclui essa orientação como uma de suas regras ( http://msdn.microsoft.com/en-us/library/ms245046(VS.80).aspx ), com as seguintes informações:
Dito isso, o primeiro comentário de David Kean resume mais sucintamente as preocupações, dizendo que isso é mais sobre estar correto do que sobre o ganho de desempenho:
fonte
Eu definitivamente transformaria tudo o que puder em estático por um motivo diferente:
Funções estáticas, quando JIT'd, são chamadas sem um parâmetro "this". Isso significa, por exemplo, que uma função não estática de 3 parâmetros (método membro) é enviada com 4 parâmetros na pilha.
A mesma função compilada como uma função estática seria chamada com 3 parâmetros. Isso pode liberar registros para o JIT e conservar espaço na pilha ...
fonte
Estou no campo "apenas tornar estáticos métodos privados". Tornar um método público pode introduzir um acoplamento que você não deseja e pode diminuir a testabilidade: você não pode criar um método estático público.
Se você quiser testar a unidade de um método que usa um método estático público, acabará testando o método estático também, que pode não ser o que você deseja.
fonte
Métodos inerentemente estáticos que, por algum motivo, são tornados não estáticos são simplesmente irritantes. A saber:
Eu ligo para meu banco e peço meu saldo.
Eles pedem o número da minha conta.
Justo. Método de instância.
Ligo para o meu banco e peço o endereço de correspondência.
Eles pedem o número da minha conta.
WTF? Falha - deveria ser um método estático.
fonte
Eu vejo isso geralmente de uma perspectiva funcional de funções puras. Precisa ser um método de instância? Caso contrário, você pode se beneficiar forçando o usuário a passar as variáveis e não mutilar o estado da instância atual. (Bem, você ainda poderia mutilar o estado, mas o objetivo é, por design, não fazer isso.) Geralmente, projeto métodos de instância como membros públicos e faço o meu melhor para tornar os membros privados estáticos. Se necessário (você pode então extraí-los mais facilmente para outras classes posteriormente.
fonte
Nesses casos, tendo a mover o método para uma biblioteca estática ou utils, então não misturo o conceito de "objeto" com o conceito de "classe"
fonte