C# - Object reference not set to an instance of an object


  Hoje veremos como tratar a exceção : 'Object reference not set to an instance of an object'

A exceção "Object reference not set to an instance of an object" é lançada quando um código tenta acessar uma referência de objeto que não foi inicializada ou que foi definida como null. Essa exceção geralmente ocorre quando um método tenta chamar um membro em um objeto que é null, ou seja, uma referência a um objeto que não aponta para nenhum objeto válido.



Por exemplo, considere o seguinte código:

string nome = null;

int length = nome.Length;

Nesse caso, a exceção "Object reference not set to an instance of an object" será lançada porque a variável nome não foi inicializada e, portanto, não aponta para nenhum objeto válido. Quando o método Length é chamado, ocorre uma tentativa de acessar um membro em um objeto que não existe, o que leva à exceção.

Para evitar essa exceção, é importante garantir que todas as variáveis que representam objetos sejam inicializadas corretamente antes de serem usadas em qualquer operação. Também é importante verificar se uma variável que pode ser null antes de tentar acessar um membro nela.

Uma das maneiras mais simples de verificar se uma variável é null é usar o operador de coalescência nula ?? :

string nome = null;

int length = (nome ?? "").Length;

Nesse caso, o operador ?? verifica se nome é null e, se for, retorna uma string vazia (""). Isso garante que a chamada ao método Length não falhe, mesmo se a variável s for null.

Esta exceção é uma das exceções mais comuns em C# e pode ocorrer em vários cenários, incluindo:

  1. Acessando uma variável que não foi inicializada ou foi definida como null.
  2. Passando um objeto nulo para um método que espera um objeto válido.
  3. Usando uma propriedade ou método de um objeto que é null.
  4. Tentando acessar um elemento de uma matriz que é null ou fora do intervalo válido.
  5. Tentando acessar um membro de um objeto que foi removido da memória ou que não existe mais.

Vejamos a seguir 3 causas principais da ocorrência desta exceção.

Causa nº 1: Acessando uma variáel que não foi inicializada

Ao tentar acessar uma variável que não foi inicializada,  a exceção "Object reference not set to an instance of an object" será lançada.

Isso ocorre porque a variável não possui um valor atribuído a ela e, portanto, não aponta para nenhum objeto válido na memória.

Quando uma variável é declarada sem ser inicializada, seu valor é definido como null por padrão. Se um código tentar acessar uma variável que é null, uma exceção será lançada. Por exemplo:

string mensagem;

Console.WriteLine(mensagem);

Nesse caso, a variável mensagem é declarada, mas não é inicializada com um valor. Quando o método Console.WriteLine tenta acessar a variável, ocorre uma tentativa de acessar um membro em um objeto que não existe, o que leva à exceção "Object reference not set to an instance of an object".

Para evitar essa exceção, é importante inicializar todas as variáveis com valores apropriados antes de usá-las em qualquer operação. Isso pode ser feito atribuindo um valor à variável no momento da declaração ou em algum ponto posterior do código antes de usá-la :

string mensagem = "Olá...";

Console.WriteLine(mensagem);

Agora mensagem é inicializada com um valor pertinente evitando a exceção.

Causa nº 2: O objeto está definido como nulo

Outra causa desta exceção é quando um objeto é definido como nulo. O Null é um valor especial que representa a ausência de um valor e pode ser atribuído a uma variável para indicar que ela não se refere a nenhum objeto no momento. Quando um objeto é definido como nulo, qualquer tentativa de acessar suas propriedades ou métodos resultará no mesmo erro.

string nome = null;

int tamanho = nome.Length;
 

No código acima, a variável nome é definida como nula e, quando a propriedade Length do objeto string é acessada, o erro é lançado. Para corrigir esse erro, a variável de texto deve ser inicializada com um valor de string válido antes que suas propriedades ou métodos sejam acessados.

Além de inicializar variáveis, podemos usar técnicas de programação defensiva para evitar este erro. A programação defensiva envolve a escrita de código que antecipa e manipula possíveis erros, como variáveis ​​nulas ou não inicializadas.

string nome = null;

if
(nome != null)
{
  
int tamanho = nome.Length;  
}

A instrução if no código de exemplo acima verifica se a variável nome é nula antes de acessar sua propriedade Length. Isso garante que o código não lançará a exceção.

Temos as seguintes alternativas ao código acima que vão atuar da mesma forma:

a-)

string nome = null;

if
(nome is not null)
{
 
int tamanho = nome.Length;
}

b-)

string nome = null;

nome ??= "sem nome";

int
tamanho = nome.Length;

c-)

string nome = null;

if (!string.IsNullOrEmpty(nome))
{
  
int tamanho = nome.Length;
}

Causa nº 3: Quando FirstOrDefault() ou SingleOrDefault() retorna null

Esta é provavelmente uma das causas mais frequentes que causam essa exceção. Isso acontecerá quando uma coleção não tiver um objeto que corresponda aos critérios do filtro. Qualquer tentativa de acessar as propriedades do objeto resultará no mesmo erro.

var usuario = _context.Usuarios.FirstOrDefault(x => x.Nome == "Maria");

var nomeCompleto = usuario.Nome + " " + usuario.Sobrenome;
 

No código acima, a exceção vai ocorrer se nenhum usuário com nome "Maria" for encontrado no banco de dados, pois o valor atribuído a variável usuário será null.

Existem várias maneiras de resolver esse problema. Primeiro, podemos usar técnicas de programação defensiva para evitar o erro:

var usuario = _context.Usuarios.FirstOrDefault(x => x.Nome == "Maria");

var nomeCompleto = "";

if (usuario != null)
   nomeCompleto= usuario.Nome +
" " + usuario.Sobrenome;
 

Em segundo lugar, também podemos usar o operador condicional nulo ? .  Este operador nos permite acessar as propriedades ou métodos de um objeto somente se o objeto não for nulo, sem lançar uma exceção se o objeto for nulo.

var usuario = _context.Usuarios.FirstOrDefault(x => x.Nome == "Maria");

var nomeCompleto = usuario?.Nome + " " + usuario?.Sobrenome;
 

Em terceiro lugar, também podemos lançar uma exceção customizada e deixar o chamador do método ou o manipulador de erro global lidar com a exceção:

var usuario = _context.Usuarios.FirstOrDefault(x => x.Nome == "Maria");

if (usuario is null)
{
 
throw new NotFoundException("Usuário não encontrado.");
}

public class NotFoundException: Exception
{
 
public NotFoundException(string mensagem) : base(mensagem)
  { }
}

Desta forma, esta exception pode ser evitada inicializando corretamente as variáveis, usando técnicas de programação defensiva, usando operadores condicionais nulos e coalescentes nulos ou lançando uma exceção personalizada que o aplicativo manipulará.

E estamos conversados ...

"Eu sou a videira, vós as varas; quem está em mim, e eu nele, esse dá muito fruto; porque sem mim nada podeis fazer."
João 15:5

Referências:


José Carlos Macoratti