Introdução: por que a questão sobre propriedades automáticas reuniu milhares de visualizações?
\n\nSe você já programou em C#, certamente já se deparou com uma questão simples, mas importante: "Como definir corretamente o valor inicial de uma propriedade automática?". Esta pergunta no Stack Overflow reuniu dezenas de milhares de visualizações, e não é à toa. A aparente simplicidade esconde várias armadilhas.
\n\nImagine: você cria a classe User e deseja que a propriedade Name não seja null por padrão, mas sim uma string vazia. Parece simples, certo? Mas na prática, os desenvolvedores cometem erros típicos de inicialização de propriedades C# que levam a NullReferenceException ou comportamentos inesperados.
Neste artigo, analisaremos o TOP 5 erros e mostraremos como evitá-los. Você aprenderá abordagens modernas — do C# 6 ao C# 12 — e entenderá qual método escolher para seu projeto.
\n\n\n\n
Erro nº1: Ignorar a inicialização de propriedades automáticas
\n\nO erro mais comum é não definir um valor inicial para tipos de referência. Muitos iniciantes escrevem:
\n\npublic class User\n{\n public string Name { get; set; } // null por padrão\n public List<string> Roles { get; set; } // null\n}\n\nEm C#, propriedades automáticas para tipos de referência são null por padrão. Isso leva a problemas com NullReferenceException quando você esquece de atribuir um valor antes de usar.
Como corrigir?
\nSempre defina explicitamente um inicializador de propriedade automática C#. A maneira mais simples é usar a sintaxe do C# 6:
\n\npublic class User\n{\n public string Name { get; set; } = string.Empty;\n public List<string> Roles { get; set; } = new List<string>();\n}\n\n\n\n\nDica: Use
\nstring.Emptyem vez de aspas vazias — isso melhora a legibilidade e segue as melhores práticas C#.
\n\n
Erro nº2: Inicialização no construtor sem considerar a cadeia de chamadas
\n\nOutro erro comum é definir o valor padrão C# apenas no construtor, ignorando os inicializadores de propriedade. Isso pode causar confusão, especialmente com herança.
\n\npublic class BaseClass\n{\n public int Value { get; set; }\n\n public BaseClass()\n {\n Value = 10;\n }\n}\n\npublic class DerivedClass : BaseClass\n{\n public DerivedClass()\n {\n // Value já = 10, mas podemos sobrescrever\n }\n}\n\nProblema: se você adicionar um inicializador à propriedade Value e mantiver a atribuição no construtor, a ordem de execução pode surpreender. Os inicializadores são executados antes do corpo do construtor da classe base, mas após a chamada do construtor da classe derivada.
Como evitar?
\nEscolha um método: ou inicializador ou construtor. É melhor preferir inicializadores de propriedades automáticas C#, pois são mais previsíveis e concisos.
\n\npublic class BaseClass\n{\n public int Value { get; set; } = 10; // Fonte única de verdade\n}\n\n\n\n
Erro nº3: Uso de campos readonly em vez de propriedades automáticas
\n\nAlguns desenvolvedores, ao tentar definir um valor inicial, abandonam as propriedades automáticas e usam campos públicos:
\n\npublic class Config\n{\n public readonly int MaxRetries = 3; // Erro: violação de encapsulamento\n}\n\nIsso é uma má prática. Campos violam o encapsulamento — você não conseguirá adicionar lógica no getter/setter sem alterar a API. Além disso, ao serializar ou usar em WPF/Blazor, isso criará problemas.
\n\nAbordagem correta
\nUse propriedades automáticas com inicialização ou propriedades init-only do C# 9:<