Inscreva-se agora

* Você receberá as últimas notícias e atualizações sobre suas celebridades favoritas!

Postagens em alta

Blog

Introdução às Tipagens Genéricas em C# – Tipos Construídos e Suas Aplicações
Aprenda C#

Introdução às Tipagens Genéricas em C# – Tipos Construídos e Suas Aplicações 

No desenvolvimento com C#, a utilização de tipos genéricos desempenha um papel fundamental na criação de códigos reutilizáveis e eficientes. Os tipos genéricos permitem que você defina classes, interfaces e métodos que não são vinculados a um tipo específico até o momento da execução. No entanto, esses tipos genéricos são apenas “modelos” até que os argumentos de tipo sejam aplicados, resultando no que chamamos de tipos construídos.

Neste post, vamos explorar em detalhes o conceito de tipos construídos, como funcionam, sua importância e como usá-los corretamente no C#.

O que é um Tipo Construído?

Um tipo construído surge quando você aplica argumentos de tipo a uma declaração genérica. Essencialmente, você “instancia” um tipo genérico ao fornecer os tipos que ele usará, transformando-o em um tipo concreto que pode ser usado em variáveis, métodos e outras expressões.

Exemplo:

namespace Widgets
{
    class Queue { /* Implementação não genérica */ }
    class Queue<TElement> { /* Implementação genérica */ }
}

namespace MyApplication
{
    using Widgets;
    class X
    {
        Queue q1; // Tipo não genérico Widgets.Queue
        Queue<int> q2; // Tipo genérico Widgets.Queue<int>
    }
}

No exemplo acima, Queue é um tipo não genérico, enquanto Queue<TElement> é genérico. Ao aplicarmos o argumento de tipo int, criamos o tipo construído Queue<int>.

Diferença Entre Tipos Genéricos e Tipos Construídos

Uma declaração de tipo genérico por si só é chamada de tipo genérico não vinculado. Esse tipo age como uma “planta” que pode ser usada para gerar vários tipos diferentes. Apenas quando um argumento de tipo é aplicado (dentro dos sinais de menor e maior < >), temos o que chamamos de um tipo construído.

Como Usar Tipos Construídos no C

Os tipos construídos podem ser utilizados em praticamente todos os lugares onde um nome de tipo pode aparecer no C#. Isso inclui declarações de variáveis, assinaturas de métodos, retorno de funções e expressões.

List<int> listaDeInteiros = new List<int>();

Nesse exemplo, List<int> é um tipo construído, com int como argumento de tipo. Isso permite que listaDeInteiros seja uma lista especificamente de inteiros.

Tipos Abertos e Tipos Fechados

Todos os tipos em C# podem ser classificados como tipos abertos ou tipos fechados:

  • Tipo Aberto: Inclui parâmetros de tipo que ainda não foram especificados. Por exemplo, List<T> é um tipo aberto, pois depende de um parâmetro de tipo T.
  • Tipo Fechado: É um tipo onde todos os parâmetros de tipo foram definidos. Por exemplo, List<int> é um tipo fechado.

No tempo de execução, todo o código é executado no contexto de tipos fechados, ou seja, tipos que têm argumentos de tipo específicos aplicados. Os tipos abertos existem apenas durante a compilação, ajudando o compilador a garantir a segurança do tipo.

Regras para o Uso de Tipos Genéricos

Para trabalhar corretamente com tipos construídos, você deve atender às restrições definidas nos parâmetros de tipo. Ao criar uma classe ou método genérico, você pode impor restrições específicas para garantir que os tipos fornecidos como argumentos atendam a certos requisitos.

Exemplo de Restrição:

class B<T> where T : IEnumerable { }
class D<T> : B<T> where T : IEnumerable { }

Nesse exemplo, T é restrito a tipos que implementem a interface IEnumerable, garantindo que você só possa usar tipos adequados que suportam essa funcionalidade.

8.5 Parâmetros de Tipo

Um parâmetro de tipo designa um identificador que pode se referir a um tipo de valor ou um tipo de referência. No entanto, devido à natureza genérica, os parâmetros de tipo têm algumas operações e restrições específicas:

  • Um parâmetro de tipo não pode ser usado diretamente para declarar uma classe base ou interface.
  • As conversões disponíveis para um parâmetro de tipo dependem das restrições aplicadas a ele.
  • O literal null não pode ser convertido para um parâmetro de tipo, exceto se o parâmetro for conhecido por ser um tipo de referência.
  • Expressões default podem ser usadas para inicializar variáveis com parâmetros de tipo.
  • Um parâmetro de tipo não pode ser usado para acessar membros estáticos ou tipos aninhados.

Exemplo:

class Outer<T>
{
    public class Inner { }
    public Inner i; // O tipo de i é Outer<T>.Inner
}

Aqui, o parâmetro de tipo T é instanciado durante o tempo de execução, ou seja, o tipo concreto só será determinado quando o argumento de tipo for passado.

Essas regras garantem que os parâmetros de tipo sejam manipulados de maneira segura e eficiente no momento da execução.

Diferença entre Tipos Vinculados e Não Vinculados

Em C#, os termos tipo vinculado e não vinculado são importantes ao lidar com tipos genéricos.

  • Tipo Não Vinculado: Refere-se a uma declaração de tipo genérico que ainda não foi associada a nenhum argumento de tipo. Por exemplo, List<T> é um tipo genérico não vinculado.
  • Tipo Vinculado: Refere-se a um tipo genérico ao qual argumentos de tipo foram aplicados. Por exemplo, List<int> é um tipo vinculado.

Um tipo não vinculado não pode ser usado como o tipo de uma variável, argumento ou retorno de método, exceto dentro de uma expressão typeof.

Aplicando Tipos Construídos em Programas C

Os tipos construídos permitem a criação de estruturas de dados e métodos altamente flexíveis e reutilizáveis. Em vez de duplicar código para diferentes tipos de dados, você pode simplesmente aplicar argumentos de tipo para adaptar seu código a diferentes cenários.

Vamos a um exemplo mais avançado, combinando genéricos com herança e interfaces:

class B<T> where T : IEnumerable { }
class D<T> : B<T> where T : IEnumerable { }
class E<T> : B<List<T>> { }

Aqui, D impõe a restrição de que T deve implementar IEnumerable, enquanto E usa a lista de T, que sempre implementa IEnumerable.

Conclusão

Os tipos construídos em C# são uma ferramenta poderosa que permite maior flexibilidade e reutilização de código. Ao entender como aplicar corretamente os argumentos de tipo e as regras associadas, você pode criar soluções mais robustas e seguras. Aproveitar essa funcionalidade em seus projetos pode tornar seu código muito mais eficiente e adaptável a diferentes cenários.

Se você já utilizou tipos construídos em seus projetos, compartilhe sua experiência nos comentários! Que tipos de desafios você encontrou ao trabalhar com genéricos em C#?

Posts relacionados

Deixe um comentário


Campos obrigatórios são marcado com *