Minha pergunta é relacionada às características de desempenho de métodos estáticos vs métodos de instância e sua escalabilidade. Suponha, para este cenário, que todas as definições de classe estão em um único assembly e que vários tipos de ponteiros discretos são necessários.
Considerar:
public sealed class InstanceClass
{
public int DoOperation1(string input)
{
// Some operation.
}
public int DoOperation2(string input)
{
// Some operation.
}
// … more instance methods.
}
public static class StaticClass
{
public static int DoOperation1(string input)
{
// Some operation.
}
public static int DoOperation2(string input)
{
// Some operation.
}
// … more static methods.
}
As classes acima representam um padrão de estilo auxiliar.
Em uma classe de instância, a resolução do método de instância leva um momento para ser oposta a StaticClass.
Minhas perguntas são:
Quando manter o estado não é uma preocupação (nenhum campo ou propriedade é necessário), é sempre melhor usar uma classe estática?
Onde houver um número considerável dessas definições de classe estática (digamos 100, por exemplo, com vários métodos estáticos cada), isso afetará o desempenho de execução ou o consumo de memória negativamente em comparação com o mesmo número de definições de classe de instância?
Quando outro método dentro da mesma classe de instância é chamado, a resolução da instância ainda ocorre? Por exemplo, usando a palavra-chave [this]
this.DoOperation2("abc")
de dentroDoOperation1
da mesma instância.
fonte
this
aponta para algo quando uma classe chama um método de instância em si mesma?"Respostas:
Em teoria, um método estático deve ter um desempenho ligeiramente melhor do que um método de instância, todas as outras coisas sendo iguais, por causa do
this
parâmetro oculto extra .Na prática, isso faz tão pouca diferença que ficará oculto no ruído de várias decisões do compilador. (Conseqüentemente, duas pessoas poderiam "provar" uma melhor do que a outra com resultados discordantes). Até porque o
this
é normalmente passado em um registro e freqüentemente está naquele registro para começar.Este último ponto significa que, em teoria, devemos esperar que um método estático que pega um objeto como parâmetro e faz algo com ele seja ligeiramente menos bom do que o equivalente como uma instância nesse mesmo objeto. Mais uma vez, porém, a diferença é tão pequena que, se você tentar medi-la, provavelmente acabará medindo alguma outra decisão do compilador. (Especialmente porque a probabilidade de essa referência estar em um registro o tempo todo também é bastante alta).
As diferenças reais de desempenho se resumem a se você tem objetos artificialmente na memória para fazer algo que deveria ser naturalmente estático, ou se você está enrolando cadeias de passagem de objetos de maneiras complicadas para fazer o que deveria ser naturalmente uma instância.
Portanto, para o número 1. Quando manter o estado não é uma preocupação, é sempre melhor ser estático, porque é para isso que serve a estática . Não é uma preocupação de desempenho, embora haja uma regra geral de jogar bem com otimizações de compilador - é mais provável que alguém se esforce para otimizar casos que surgem com uso normal do que aqueles que surgem com uso estranho.
Número 2. Não faz diferença. Há uma certa quantia de custo por classe para cada membro em termos de quantos metadados existem, quanto código existe no arquivo DLL ou EXE real e quanto código modificado haverá. É o mesmo, seja instância ou estático.
Com o item 3,
this
é comothis
faz. No entanto, observe:O
this
parâmetro é passado em um determinado registro. Ao chamar um método de instância dentro da mesma classe, ele provavelmente já estará naquele registro (a menos que tenha sido armazenado e o registro usado por algum motivo) e, portanto, não há nenhuma ação necessária para definir othis
que ele precisa ser definido para . Isso se aplica até certo ponto, por exemplo, os dois primeiros parâmetros do método sendo os dois primeiros parâmetros de uma chamada que ele faz.Como ficará claro que
this
não é nulo, isso pode ser usado para otimizar chamadas em alguns casos.Uma vez que ficará claro que
this
não é nulo, isso pode tornar as chamadas de método embutidas mais eficientes novamente, já que o código produzido para falsificar a chamada do método pode omitir algumas verificações de nulo que podem precisar de qualquer maneira.Dito isso, cheques nulos são baratos!
É importante notar que métodos estáticos genéricos atuando em um objeto, em vez de métodos de instância, podem reduzir alguns dos custos discutidos em http://joeduffyblog.com/2011/10/23/on-generics-and-some-of- the-associated-overheads / no caso em que determinado estático não é chamado para um determinado tipo. Como ele coloca, "Como um aparte, os métodos de extensão são uma ótima maneira de tornar as abstrações genéricas mais pagas".
No entanto, observe que isso se refere apenas à instanciação de outros tipos usados pelo método, que de outra forma não existem. Como tal, ele realmente não se aplica a muitos casos (algum outro método de instância usou esse tipo, algum outro código em outro lugar usou esse tipo).
Resumo:
Edit: Uma nota sobre o quão baratos são os cheques nulos (que afirmei acima). A maioria das verificações de nulo no .NET não verifica nada em relação a nulo, em vez disso, continua o que faria com a suposição de que funcionará e, se ocorrer uma exceção de acesso, ela será transformada em um
NullReferenceException
. Como tal, principalmente quando conceitualmente o código C # envolve uma verificação de nulo porque está acessando um membro da instância, o custo se for bem-sucedido será, na verdade, zero. Uma exceção seriam algumas chamadas inline, (porque eles querem se comportar como se tivessem chamado um membro da instância) e eles apenas acessam um campo para acionar o mesmo comportamento, então eles também são muito baratos e ainda podem ser deixados de fora de qualquer maneira (por exemplo, se a primeira etapa do método envolvia acessar um campo como ele era).fonte
this
meio de um parâmetro explícito. Um impacto maior aqui seria o quão próximos os dados estão de dados relacionados (campos de tipo de valor ou valores de array estão mais próximos do que dados em campos de tipo de referência) e padrões de acesso.obj.DoSomehting(2)
ser um pouco mais barato do que,DoSomething(obj, 2)
mas como eu também disse, a diferença é tão pequena e depende de coisas minúsculas que podem acabar diferentes na compilação final que realmente não vale a pena se preocupar. Se você está fazendo algo tão caro (em relação ao tipo de diferenças em jogo aqui) como serializar algo em uma corda, então é especialmente inútil.ctor
ainda requer a inicialização de todos os campos. Assim que você já tiver uma instância, esta resposta se aplica ("todas as outras coisas sendo iguais"). Obviamente, umcctor
método caro também pode tornar os métodos estáticos lentos, mas isso é apenas na primeira chamada e se aplica igualmente aos métodos de instância. Consulte também docs.microsoft.com/en-us/previous-versions/dotnet/articles/…Eu diria que sim. Ao declarar algo,
static
você declara uma intenção de execução sem estado (não é obrigatório, mas uma intenção de algo que seria de esperar)Não pense assim, a menos que você tenha certeza de que as classes estáticas são realmente contínuas, porque senão é fácil bagunçar as alocações de memória e obter vazamentos de memória.
Não tenho certeza sobre esse ponto (este é um detalhe puramente de implementação do CLR), mas acho que sim.
fonte
métodos estáticos são mais rápidos, mas menos OOP, se você for usar padrões de design, método estático provavelmente código ruim, para escrever lógica de negócios melhor sem estática, funções comuns como leitura de arquivo, WebRequest etc. responda
fonte