where
em C#.19/12/2024
Neste artigo, exploraremos o uso de classes genéricas com restrições usando a palavra-chave where.
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
.
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}
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}
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}
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}
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.
Editar<T>
pode ser usada em diferentes contextos sem duplicar lógica.where
garantem que apenas tipos apropriados sejam utilizados.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.