Como exatamente funcionam os mecanismos genéricos comumente usados pelos programadores?


Autor | Zhu Gang, Editor-chefe | Guo Rui

CSDN Baixe do Oriental IC

Exposição | CSDN (ID: CSDNnews)

Os desenvolvedores costumam usar genéricos, e a maioria dos desenvolvedores usa muito bem os genéricos. Os genéricos precisam do suporte do tempo de execução subjacente.Os parâmetros de tipo na classe genérica se tornam metadados.Eles serão usados ​​para construir a classe apropriada quando necessário no tempo de execução.Portanto, os genéricos suportam herança, polimorfismo e encapsulamento. Para falar brevemente sobre o profundo conhecimento dos genéricos, vamos dar uma olhada no que é o mecanismo interno dos genéricos.

CIL significa genérico

Após a compilação, a classe genérica não é muito diferente do resultado da compilação da classe comum.O resultado é CIL e metadados.A única diferença é que o CIL usará uma marca especial para indicar que o resultado da compilação é uma classe genérica. Compile os resultados, vamos dar uma olhada em um exemplo.

public class Demo<T> where T:IComparable


{


    //more code


    T[] item;


    //more code


}

O código acima define uma classe genérica de demonstração, que contém um parâmetro de tipo. O código CIL parametrizado finalmente gerado após a mutação é o seguinte:

.class private auto ansi beforefieldinit Demo'1 <[mscorlib]System.IComparable)T> extends [mscorlib]System.Object


{


    //more CIL code


    .field private !0[ ] items


    //more CIL code


}

No código CIL parametrizado acima, vemos um '1' após a Demo, que é chamado de número de argumentos, ou seja, o número de parâmetros, indicando o número de argumentos de tipo necessários ao declarar uma classe genérica.O exemplo acima tem apenas um tipo Portanto, o número de parâmetros reais de tipo que ele precisa é 1. Se for uma classe genérica como Demo <TKey, TValue, Tother>, a quantidade de parâmetros reais de tipo no código CIL parametrizado gerado é 3, que é expresso como '3 . As restrições impostas à classe são mostradas no código CIL parametrizado, ambos [mscorlib] System.IComparable. Ao mesmo tempo, o código CIL modifica a declaração da matriz de tipos T definida, usando! Para incluir um parâmetro de tipo. Exceto pelos três pontos mencionados acima, o outro código CIL gerado não é diferente do código gerado pelas classes comuns.

Instanciação genérica do tipo de valor

Ao construir um tipo genérico com um tipo de valor como parâmetro de tipo, para criar um tipo genérico concreto, o tempo de execução colocará o parâmetro de tipo especificado no local apropriado do CIL.

Quando chamamos a classe genérica Demo definida na seção anterior pela primeira vez e passamos int como um argumento de tipo para Demo, o tempo de execução gera uma versão concreta de Demo e usa int para substituir o parâmetro de tipo. Dessa forma, toda vez que você usar Demo <int>, a classe de materialização gerada Demo <int> será reutilizada no tempo de execução. Deve-se notar aqui que a classe materializada gerada é apenas para o caso em que o argumento de tipo é int.Se uma demonstração com float como o argumento de tipo for definida neste momento, outro tipo genérico será gerado em tempo de execução. Versão.

O uso de instâncias genéricas de tipo de valor pode evitar operações de conversão e boxe de código para melhorar o desempenho, mas no processo de uso, você também precisa julgar se os genéricos de tipo de valor devem ser usados ​​e como usá-los de acordo com códigos específicos, situações específicas e itens específicos.

Dica: O tempo de execução criará um tipo genérico específico para cada novo parâmetro somente de tipo.

Instanciação genérica do tipo de referência

Instâncias genéricas são um pouco diferentes dos tipos de valor ao usar tipos de referência como argumentos de tipo. Ao construir um tipo genérico, o tempo de execução usará a referência de objeto para substituir o parâmetro de tipo no código CIL para criar o tipo genérico materializado Sempre que o tipo construído for instanciado usando o parâmetro de tipo de referência, o tempo de execução reutilizará o gerado Versão, aqui você deve prestar atenção que, se o tipo de referência fornecido for diferente do tipo de referência ao construir o tipo genérico, ele ainda utilizará a versão gerada. Vejamos um exemplo:

Demo<User> userDemo;


Demo<Student> studentDemo;

Antes de tudo, quando o código for executado na primeira linha, uma versão específica da Demo será gerada em tempo de execução.O CIL não armazenará User como o tipo de dados especificado, mas armazenará a referência do objeto. Então, quando o código for executado na segunda linha, embora as referências de Student e User sejam diferentes, o CIL não criará uma nova versão materializada do Student, mas instanciará a instância Demo da referência de objeto fornecida anteriormente. Obviamente, para garantir a segurança do tipo, o CIL alocará uma área de memória do tipo Pedido para substituir cada referência de objeto do parâmetro type para essa área de memória. O benefício do uso de genéricos de tipo de referência é que o compilador compacta as classes materializadas que cria para uma, reduzindo bastante a quantidade de código e melhorando o desempenho do código.

Deve-se observar aqui que o parâmetro do tipo de referência usa a mesma definição de tipo genérico interno quando é alterado, mas se a seguinte situação ocorrer, a mesma definição de tipo genérico interno não será aplicada.

Demo<int,User> userDemo;


Demo<long,User> userLongDemo;


Demo<Guid,User> userGuidDemo;

No código acima, o parâmetro type contém o tipo de valor.Neste momento, a mesma definição de tipo genérico interno não será usada, mas uma definição de tipo interno diferente será criada para cada demonstração.

Sumário

Embora este artigo seja curto, ele explica completamente os princípios internos do mecanismo genérico e as precauções relacionadas. Os genéricos no .NET são sem dúvida os melhores. O uso de genéricos em Java é completamente implementado no compilador, e não na JVM. Embora isso impeça o uso de genéricos e a distribuição de novas JVMs, é porque Não faz distinção entre tipos de valor e tipos de referência, portanto, a eficiência da implementação e afeta o uso da parte de reflexão.

Autor: aço Zhu, .NET engenheiro de desenvolvimento sênior, 7 anos de experiência em desenvolvimento de linha de frente, participou no desenvolvimento de sistemas de governo eletrônico e sistemas de atendimento ao cliente AI, e recrutamento Internet arquitetura do site, atualmente trabalhando em Pequim Chong Heng Rong-hui Technology Development Co., Ltd.

Isenção de responsabilidade: este artigo é um envio original pelo autor, não reimprima sem permissão.

【FIM】

Recomendações mais interessantes

Um século da IBM finalmente All In inteligência artificial e nuvem híbrida!

☞ Microsoft, Apple, Google, Samsung ... Esses gigantes da tecnologia no blockchain já fizeram tantas coisas!

☞Vencendo o GitHub 2000+ Star, como a plataforma de aprendizado de máquina de código aberto Alink da Alibaba Cloud supera o duplo "jogo" de 11 dados? Ecologia da tecnologia da IA

Ic A Microsoft adquiriu uma empresa para uma pessoa? Crack programas da Sony, escreva romances de hackers e assista a sua dura vida no programa!

Modelo de projeto de aprendizado de máquina: 6 etapas básicas do projeto de ML

IBM, Microsoft, Apple, Google, Samsung ... Esses gigantes da tecnologia no blockchain já fizeram tantas coisas!

Resumo dos programadores seniores: vou lhe contar todas as 6 maneiras de analisar o processo Linux

Bem-estar de hoje: se você deixar um comentário na área de comentários, poderá obter um ingresso para a transmissão ao vivo da "Conferência dos Dez Mil Desenvolvedores da IA ​​2020" no valor de 299 yuan . Venha e mova seu dedo e escreva o que você quer dizer.

Clique para ler o texto original, maravilhoso para continuar!

Todo "assistindo" você pede, eu levo isso a sério

Artigos publicados em 1940 · 40 mil curtidas + · 18,13 milhões de visualizações

Acho que você gosta

Origin blog.csdn.net/csdnnews/article/details/105424407
Recomendado
Clasificación