Utilizando Classes Genéricas e Restrições com where em C#.

19/12/2024

Neste artigo, exploraremos o uso de classes genéricas com restrições usando a palavra-chave where.

Utilizando Classes Genéricas e Restrições com where em C#

Classes genéricas são um recurso poderoso no C# que permite reutilizar código de maneira eficiente, garantindo flexibilidade e segurança de tipo. Neste artigo, exploraremos o uso de classes genéricas com restrições usando a palavra-chave where. Utilizaremos como exemplo uma estrutura baseada nas classes Editar<T>, Item, ItemOrcamento, ItemPedido, Orcamento, e Pedido.

Estrutura do Exemplo

Classe Base: Item

A classe Item atua como uma base para tipos de itens que serão usados em orçamentos e pedidos.

1public abstract class Item
2{
3    public int Id { get; set; }
4    public string Descricao { get; set; }
5    public decimal Valor { get; set; }
6    public int Quantidade { get; set; }
7    public decimal Desconto { get; set; }
8    public decimal Total => Quantidade * Valor;
9}

Subclasses: ItemOrcamento e ItemPedido

Essas subclasses estendem a funcionalidade de Item para representar itens em diferentes contextos.

1public class ItemOrcamento : Item
2{
3    // Propriedades especializadas
4}
5
6public class ItemPedido : Item
7{
8    // Propriedades especializadas
9}

Classe Genérica: Editar<T>

A classe genérica Editar<T> define a estrutura principal para manipulação de itens, com restrições que garantem que T seja uma subclasse de Item.

1public abstract class Editar<T> where T : Item
2{
3    protected List<T> Itens { get; } = new List<T>();
4
5    public void AdicionarItem(T item)
6    {
7        Itens.Add(item);
8    }
9
10    public void RemoverItem(int itemId)
11    {
12        var item = Itens.FirstOrDefault(i => i.Id == itemId);
13        if (item != null)
14        {
15            Itens.Remove(item);
16        }
17    }
18
19    public decimal Total => Itens.Sum(x => x.Valor);
20
21    public void AplicarDesconto(decimal percentual)
22    {
23        foreach (var item in Itens)
24        {
25            item.Desconto = item.Valor * (percentual / 100);
26        }
27    }
28
29    public void RemoverDesconto()
30    {
31        foreach (var item in Itens)
32        {
33            item.Desconto = 0;
34        }
35    }
36}

Classes Especializadas: Orcamento e Pedido

Essas classes herdam de Editar<T> e especificam o tipo de item a ser manipulado.

1public class Orcamento : Editar<ItemOrcamento>
2{
3    public string Cliente { get; set; }
4
5    // Propriedades especializadas
6}
7
8public class Pedido : Editar<ItemPedido>
9{
10    public string Numero { get; set; }
11    public decimal Frete { get; set; }
12    public decimal PrecoTotal => Total + Frete;
13
14    // Propriedades especializadas
15}

Conceitos do SOLID em Uso

A implementação apresentada adota vários princípios do SOLID:

Princípio da Segregação de Interfaces (ISP)

As classes Item, ItemOrcamento, e ItemPedido segregam responsabilidades, garantindo que cada classe manipule somente dados relevantes ao seu contexto.

Princípio da Substituição de Liskov (LSP)

O uso de uma classe base Item permite que qualquer subclass (ItemOrcamento ou ItemPedido) seja utilizada de maneira intercambiável na classe Editar<T>, sem comprometer o comportamento esperado.

Princípio Aberto/Fechado (OCP)

A classe Editar<T> é aberta para extensão (por exemplo, Orcamento e Pedido), mas fechada para modificação direta. Novos tipos podem ser adicionados sem alterar o código existente.

Princípio da Responsabilidade Única (SRP)

Cada classe possui uma única responsabilidade: Editar<T> gerência listas de itens; adiciona descontos; calcula totais. Orcamento, ItemOrcamento, ItemPedido e Pedido lidam com contextos específicos.

Benefícios da Abordagem

  1. Reutilização de Código: A classe genérica Editar<T> pode ser usada em diferentes contextos sem duplicar lógica.
  2. Segurança de Tipo: Restrições com where garantem que apenas tipos apropriados sejam utilizados.
  3. Flexibilidade: Permite criar novas funcionalidades (como novos tipos de itens) sem modificar classes existentes.
  4. Manutenção Simples: Seguir os princípios do SOLID facilita a leitura e alterações no código.

Conclusão

Classes genéricas combinadas com restrições em C# são uma ferramenta poderosa para criar códigos modulares, reutilizáveis e aderentes a boas práticas de design. Ao implementar estruturas como Editar<T>, é possível maximizar a flexibilidade enquanto se mantém um código limpo e bem organizado.