Entendendo as propriedades do C#
O C# 11, introduzido com o .NET 7, trouxe uma adição interessante às propriedades: a palavra-chave required. Neste artigo, exploraremos as propriedades do C#, usando exemplos do conciso tutorial em vídeo de Tim Corey sobre " Atualização do .NET 7: Propriedades Obrigatórias em 10 Minutos ou Menos ". Vamos abordar tudo, desde os conceitos básicos de propriedades até a nova palavra-chave required e como ela ajuda a impor regras de inicialização.
Propriedades em C
Em C#, as propriedades permitem encapsular campos e gerenciar o acesso aos membros de dados da classe de um objeto. São comumente utilizados para garantir a integridade dos dados, permitindo ao mesmo tempo o acesso externo. Um campo privado pode ser encapsulado usando propriedades, oferecendo controle sobre como os dados são acessados ou modificados. Propriedades públicas do tipo string frequentemente utilizam métodos especiais chamados acessadores (get e set) para manipular membros da classe de forma eficiente. Em C#, uma propriedade estática pode ser acessada sem instanciar a classe, oferecendo uma maneira única de gerenciar valores de propriedades.
Veja como Tim configura um exemplo simples de propriedade para demonstrar.
Criando um aplicativo de console
Primeiro, Tim começa com um aplicativo de console básico do .NET 7 usando C# 11. Esta versão introduz a palavra-chave required, que não está disponível em versões anteriores do .NET.
Definindo um Modelo Simples
Tim cria uma classe PersonModel com propriedades para FirstName e LastName:
public class PersonModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class PersonModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Essas propriedades permitem que PersonModel armazene nomes e sobrenomes. No entanto, sem configuração adicional, FirstName e LastName podem potencialmente ficar não inicializados, levando a valores nulos.
Utilizando construtores para garantir a inicialização
Uma maneira comum de garantir que as propriedades sejam sempre inicializadas é por meio de um construtor. No exemplo de Tim, ele adiciona um construtor à classe base de PersonModel que requer tanto FirstName quanto LastName:
public PersonModel(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public PersonModel(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
Essa abordagem impõe que, sempre que um objeto PersonModel for criado, tanto FirstName quanto LastName devem ser fornecidos. Se tentássemos criar um PersonModel sem especificar esses valores, o compilador o sinalizaria como um erro.
Contexto anulável
A partir do .NET 6 e C# 10, o C# introduziu tipos de referência anulável. Isso significa que as propriedades precisam ser inicializadas ou marcadas explicitamente como anuláveis usando um ?. Por exemplo, se FirstName e LastName puderem ser nulos, nós os definiríamos da seguinte forma:
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
No exemplo de Tim, no entanto, assumimos que FirstName e LastName devem ser sempre não nulos. Inicialmente, a nulidade era tratada com inicialização cuidadosa ou anotações anuláveis, mas com o C# 11, temos opções mais robustas.
Apresentando a palavra-chave necessária
Embora construtores possam impor a inicialização, o C# 11 introduz a palavra-chave required, tornando mais fácil garantir que propriedades específicas sejam definidas. Com required, você pode marcar propriedades individuais como requeridas, o que significa que elas devem receber um valor durante a inicialização do objeto.
Configurar as propriedades necessárias
Para tornar FirstName e LastName propriedades requeridas, Tim às 4:15 modifica a classe PersonModel da seguinte maneira:
public class PersonModel
{
public required string FirstName { get; set; }
public required string LastName { get; set; }
}
public class PersonModel
{
public required string FirstName { get; set; }
public required string LastName { get; set; }
}
Ao marcar essas propriedades com required, o compilador agora exigirá que sejam definidas, seja através de um inicializador de objeto ou de um construtor. Isso é útil porque permite exigir propriedades específicas sem precisar criar um construtor.
Exemplo de uso com propriedades obrigatórias
Agora, podemos criar e inicializar PersonModel da seguinte forma:
PersonModel person = new() { FirstName = "Tim", LastName = "Corey" };
PersonModel person = new() { FirstName = "Tim", LastName = "Corey" };
Se omitirmos FirstName ou LastName, o compilador sinalizará um erro, nos levando a inicializar essas propriedades requeridas.
Utilizando o parâmetro required com construtores.
Tim demonstra um caso onde tanto propriedades required quanto construtores são usados. Em situações onde você tem um construtor que define propriedades obrigatórias, o C# precisa garantir que essas propriedades ainda estejam inicializadas quando o construtor for chamado.
Nesses casos, o atributo SetsRequiredMembers pode ser usado para sinalizar que o construtor cumpre as condições requeridas. Eis como Tim aplica isso:
[SetsRequiredMembers]
public PersonModel()
{
FirstName = "Test";
LastName = "Test";
}
[SetsRequiredMembers]
public PersonModel(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
[SetsRequiredMembers]
public PersonModel()
{
FirstName = "Test";
LastName = "Test";
}
[SetsRequiredMembers]
public PersonModel(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
Adicionar SetsRequiredMembers informa ao compilador que essas propriedades serão definidas dentro do construtor, evitando erros de inicialização. Essa funcionalidade ajuda a evitar omissões acidentais, ao mesmo tempo que permite flexibilidade na forma como as propriedades são inicializadas.
Por que as propriedades obrigatórias são úteis
Tim explica que a nova palavra-chave required agiliza o processo de garantir que as propriedades sejam sempre definidas. Em vez de precisar de construtores para o método set em todos os casos ou correr o risco de ter propriedades não definidas, agora temos uma maneira simples de exigir valores específicos diretamente na declaração da propriedade.
Essa funcionalidade se destaca em modelos de dados onde certos campos são obrigatórios e pode ajudar a detectar problemas no início do processo de desenvolvimento, evitando erros de valor nulo em tempo de execução.
Exemplo de propriedades adicionais
Tim então adicionou uma propriedade opcional, Email, que pode ser anulável:
public string? Email { get; set; }
public string? Email { get; set; }
Porque não está marcada com required, a propriedade Email pode permanecer não definida sem causar erros de compilador. Com esse exemplo, Tim demonstrou a flexibilidade que isso permite para uma classe com uma distinção clara entre campos de dados essenciais e opcionais.
Conclusão
A adição de propriedades obrigatórias no C# 11 é um recurso valioso para desenvolvedores, garantindo que as propriedades essenciais sejam sempre inicializadas. O vídeo de Tim Corey oferece uma excelente introdução a esse recurso e demonstra como ele funciona em um aplicativo de console. Ao combinar a palavra-chave required com inicializadores de objeto e construtores, podemos criar modelos de dados mais robustos e seguros em C#. Para tutoriais mais informativos, visite o canal do Tim no YouTube .
