Desafio C#

Null-forgiving e avisos do compilador

Enunciado

Crie um método ObterNome() que retorna string?. No Main, chame esse método e use o operador ! para suprimir o aviso de possível nulo ao acessar .Length. Imprima o comprimento. Em seguida, modifique o método para retornar null e mostre o que acontece se você usar ! sem verificar (comente a linha que causa exceção).

Requisitos

  • Definir static string? ObterNome() que retorna null.
  • No Main, usar string nome = ObterNome()!; para suprimir o aviso.
  • Imprimir nome.Length (que lançará exceção se null).
  • Comentar a linha problemática e imprimir uma mensagem segura.

Código inicial

using System;

class Program
{
    static string? ObterNome()
    {
        return null;
    }

    static void Main()
    {
        // Seu código aqui
    }
}

Saída esperada

Comprimento: 0
Nome não disponível
Ver dica

Use ! para suprimir o aviso, mas cuidado: se o valor for realmente nulo, o programa quebra. Para a saída esperada, trate o nulo com ?? ou verificação.

Mostrar solução
using System;

class Program
{
    static string? ObterNome()
    {
        return null; // pode retornar nulo
    }

    static void Main()
    {
        // Usando ! para suprimir o aviso do compilador
        string nome = ObterNome()!;
        // Console.WriteLine($"Comprimento: {nome.Length}"); // Lançaria NullReferenceException

        // Para evitar a exceção, verificamos ou usamos ??
        string nomeSeguro = ObterNome() ?? "";
        Console.WriteLine($"Comprimento: {nomeSeguro.Length}");

        // Alternativa: verificar explicitamente
        string? nome2 = ObterNome();
        if (nome2 is null)
        {
            Console.WriteLine("Nome não disponível");
        }
        else
        {
            Console.WriteLine($"Comprimento: {nome2.Length}");
        }
    }
}

Passo a passo

  1. ObterNome retorna string?, indicando que pode ser nulo.
  2. string nome = ObterNome()!; usa o operador null-forgiving para dizer ao compilador que confiamos que não é nulo. Isso remove o aviso, mas não altera o valor.
  3. A linha comentada nome.Length lançaria NullReferenceException porque nome é de fato nulo.
  4. Para evitar a exceção, usamos ObterNome() ?? "" para obter uma string vazia se for nulo, e imprimimos o comprimento (0).
  5. Em seguida, usamos uma verificação explícita com is null para imprimir a mensagem segura.

Por que funciona

O operador ! é uma promessa ao compilador: "eu sei que não é nulo". Ele suprime avisos, mas não realiza verificação em tempo de execução. Portanto, se o valor for nulo, o acesso a membros lançará exceção. A solução correta é usar ??, ?. ou verificação explícita para lidar com o nulo de forma segura.

Erros comuns

  • Usar ! sem garantia: string nome = ObterNome()!; Console.WriteLine(nome.Length); lança NullReferenceException. O ! não impede o erro.
  • Ignorar avisos do compilador: se você não usar ! nem tratar o nulo, o compilador emite aviso CS8602. Trate-o como um alerta real.
  • Confundir ! com ?.: ! não é um operador de acesso seguro; é apenas uma supressão de aviso.

Outra forma de resolver

Usar ?. diretamente:

Console.WriteLine($"Comprimento: {ObterNome()?.Length ?? 0}");

Ou usar pattern matching:

if (ObterNome() is string nome3)
    Console.WriteLine($"Comprimento: {nome3.Length}");
else
    Console.WriteLine("Nome não disponível");

Saída esperada

Comprimento: 0
Nome não disponível