A programação orientada a objetos (POO) é um paradigma que organiza o código de forma modular e reutilizável. Um dos pilares desse paradigma é o encapsulamento, que visa proteger os dados e o comportamento de uma classe, tornando-os acessíveis e modificáveis de maneira controlada. Um dos principais mecanismos para alcançar o encapsulamento em C# é o uso de propriedades com os modificadores “get” e “set”. Neste artigo, exploraremos como essas propriedades podem ser utilizadas para proteger os dados, promovendo uma arquitetura mais segura, modular e de fácil manutenção.

O que é encapsulamento?

O encapsulamento é o princípio que busca esconder os detalhes internos de implementação de uma classe, permitindo que sua interface pública (as propriedades e métodos) seja usada sem que o consumidor da classe precise entender ou acessar diretamente seus dados internos. Esse conceito não só protege o estado interno da classe, mas também oferece a oportunidade de validar e controlar como os dados são acessados e modificados.

Para entendermos melhor, vamos imaginar que estamos construindo uma classe “ContaBancaria”. Sem encapsulamento, qualquer código poderia acessar diretamente o saldo da conta e alterá-lo sem restrições:

				
					public class ContaBancaria
{
    public decimal Saldo;
}

var conta = new ContaBancaria();
conta.Saldo = -500; // O saldo foi alterado para um valor inválido

				
			

Com encapsulamento, podemos proteger esse campo, tornando o acesso ao saldo restrito e controlado:

				
					public class ContaBancaria
{
    private decimal saldo; // Mudamos o campo para privado

    public decimal Saldo
    {
        get { return saldo; }
        set
        {
            if (value < 0)
                throw new ArgumentException("O saldo não pode ser negativo.");
            saldo = value;
        }
    }
}

				
			

Nesse exemplo, usamos uma propriedade com um “set” que inclui uma lógica de validação para garantir que o saldo (value) não seja negativo, protegendo o estado da classe.

Propriedades com get e set

Em C#, uma propriedade é um mecanismo que permite encapsular o acesso a um campo de uma classe. O uso das palavras-chave “get” e “set” permite criar uma interface controlada para acessar e modificar o valor de um campo.

Propriedades automáticas

Quando não é necessária lógica adicional para o “get” ou “set”, você pode usar propriedades automáticas, onde o compilador cuida internamente da implementação dos campos:

				
					public class Pessoa
{
    public string Nome { get; set; } 
}

				
			

Esse código permite o acesso à propriedade “Nome” com os métodos “get” e “set”. No entanto, esse método não permite nenhuma validação ou controle.

Propriedades personalizadas com lógica interna

Você pode adicionar lógica personalizada dentro dos métodos “get” e “set”. Vamos usar um exemplo de uma classe “Pessoa” que valida a idade antes de permitir que ela seja modificada:

				
					public class Pessoa
{
    private int idade;

    public int Idade
    {
        get { return idade; }
        set
        {
            if (value < 0)
                throw new ArgumentException("Idade não pode ser negativa.");
            idade = value;
        }
    }
}

				
			

Neste exemplo, a propriedade “Idade” controla a alteração do campo “idade”, garantindo que a idade seja sempre válida.

Modificadores de acesso em propriedades

Em C#, você pode definir a visibilidade de um “get” ou “set” usando modificadores de acesso. Esses modificadores determinam a acessibilidade da propriedade e seu valor.

private set

Se você deseja que uma propriedade seja somente de leitura para os consumidores da classe, mas ainda permita modificações dentro da própria classe, você pode usar “private set”:

				
					public class Pessoa
{
    public string Nome { get; private set; }

    public Pessoa(string nome)
    {
        Nome = nome;
    }
}

var pessoa = new Pessoa("João");      
Console.WriteLine($"Nome: {pessoa.Nome}");

				
			

Neste caso, a propriedade “Nome” só pode ser atribuída por meio do construtor, impedindo a modificação direta do valor (por exemplo, Pessoa.Nome = “Pedro” não seria permitido). O método “get” não é privado, o que significa que a propriedade pode ser acessada e lida de fora da classe.

Somente leitura (get sem set)

Quando você deseja que uma propriedade seja somente leitura, ou seja, seu valor pode ser acessado mas nunca modificado após a inicialização, você pode criar uma propriedade com apenas um “get”:

				
					public class Produto
{
    public decimal Preco { get; }

    public Produto(decimal preco)
    {
        Preco = preco;
    }
}

				
			

Neste caso, “Preco” só pode ser atribuído durante a construção do objeto, garantindo que o valor não seja alterado acidentalmente após a criação.

Campos privados e propriedades públicas

Uma das práticas recomendadas em C# é manter os campos de dados internos de uma classe privados e expô-los de forma controlada através de propriedades públicas. Isso permite que você adicione lógica de validação, formatação e outras operações sem expor diretamente os campos.

				
					public class Pessoa
{
    private string nome;
    public string Nome
    {
        get { return nome; }
        set { nome = value.Trim(); } // Remover espaços extras ao atribuir
    }
}

				
			

Neste exemplo, a propriedade “Nome” controla o acesso ao campo privado “nome” e aplica uma lógica para remover espaços extras antes de atribuir um valor ao campo.

Exemplo

Agora que entendemos como funciona o encapsulamento, vamos aplicá-lo em uma situação real. Vamos simular um sistema de venda de lanches onde vamos criar uma classe “Pedido” com uma lista de “Itens”. Cada Item terá um preço, e a classe “Pedido” calculará o “PrecoTotal” dinamicamente com base nos preços dos itens.

Vamos iniciar criando a classe “Item” e “Pedido”:

				
					public class Item
{
    public string Nome { get; set; }
    public decimal Preco { get; set; }

    public Item(string nome, decimal preco)
    {
        Nome = nome;
        Preco = preco;
    }
}

public class Pedido
{
    public List<Item> Itens { get; set; } = new List<Item>();
    public decimal PrecoTotal
    {
        get
        {
            return Itens.Sum(item => item.Preco);         
         }
    }

    public void AdicionarItem(Item item)
    {
        Itens.Add(item);
    }
}

				
			

No objeto “Pedido”, teremos uma lista de “Item” contendo os itens da venda. Além disso, teremos uma propriedade chamada “PrecoTotal”, que será uma propriedade calculada, responsável por retornar o preço total do pedido. Esse cálculo é feito utilizando o método “Sum” do LINQ, que soma todos os valores presentes na propriedade “Preco” de cada item. Também vamos adicionar o método “AdicionarITem” para adicionar novos itens à lista de pedidos.

Agora vamos implementar  essa lógica:

				
					public class Program
{
    public static void Main()
    {
        var item1 = new Item("X-Tudo", 20.50m);
        var item2 = new Item("X-Salada", 10.75m);
        var item3 = new Item("X-Egg", 8.99m);

        var pedido = new Pedido();

        pedido.AdicionarItem(item1);
        pedido.AdicionarItem(item2);
        pedido.AdicionarItem(item3);

        Console.WriteLine($"Preço total do pedido: R$ {pedido.PrecoTotal:F2}");
    }
}

				
			

No exemplo acima, criamos três itens: X-Tudo, X-Salada e X-Egg. Em seguida, instanciamos um novo “Pedido” e adicionamos esses itens utilizando o método “AdicionarItem”. Por fim, mostramos o preço total do pedido calculado dinamicamente. Isso é muito útil, pois não precisamos realizar manualmente a soma dos valores de todos os itens da lista. Basta acessar a propriedade “PrecoTotal”, e o valor será calculado automaticamente.

Acelere a sua carreira conosco!

Se você é Desenvolvedor .NET Júnior e quer acelerar sua carreira até nível Pleno com salário de R$7k+, ou mesmo busca a primeira vaga, conheça a Mentoria .NET StartClique aqui

Se é Desenvolvedor .NET Pleno ou Sênior e quer virar referência técnica em sua equipe e mercado, com salário de R$10k+, conheça a Mentoria .NET ExpertClique aqui

Conclusão

O uso de propriedades com “get” e “set” em C# é uma das melhores práticas de encapsulamento. Ao proteger os campos internos da classe e fornecer uma interface controlada para acesso e modificação, você melhora a segurança, modularidade e manutenção do seu código. Além disso, o uso de propriedades permite que você adicione lógica de validação e outras verificações sem comprometer a integridade dos dados.