Em C#, o literal null é usado para indicar a ausência de um valor. Um tipo anulável é um tipo que permite valores null.
Antes do C# 8.0, os tipos de referência sempre eram anuláveis e os tipos de valor não. Um tipo de valor pode se tornar anulável acrescentando-se um ponto de interrogação a ele (?).
string nullableReferenceType = "hello";
nullableReferenceType = null; // Valid as type is nullable
int nonNullableValueType = 5;
nonNullableValueType = null; // Compile error as type is not nullable
int? nullableValueType = 5; // Define nullable value type
nullableValueType = null; // Valid as type is nullable
Acessar um membro de uma variável nula não causa erro de compilação, mas faz com que uma NullReferenceException seja lançada em tempo de execução:
string sentence = null;
// Throws NullReferenceException at runtime
sentence.Length;
Para combater esse tipo comum de erro, o C# 8 permite adotar um recurso que torna os tipos de referência não anuláveis por padrão:
string nonNullableReferenceType = "book";
nonNullableReferenceType = null; // Compile warning (no error!)
string? nullableReferenceType = "movie";
nullableReferenceType = null; // Valid as type is nullable
Para trabalhar com segurança com valores anuláveis, verifique se eles são null antes de usá-los:
string NormalizedName(string? name)
{
if (name == null)
{
return "UNKNOWN";
}
// Value is not null at this point, so no compile warning
// and no runtime NullReferenceException being thrown
return name.ToUpper();
}
NormalizedName(null); // => "UNKNOWN"
NormalizedName("Elisabeth"); // => "ELISABETH"
O operador ?? permite retornar um valor padrão quando o valor é null:
string? name1 = "John";
name1 ?? "Paul"; // => "John"
string? name2 = null;
name2 ?? "George"; // => "George"
O operador ?. permite chamar membros com segurança em um valor que pode ser null:
string? fruit = "apple";
fruit?.Length; // => 5
string? vegetable = null;
vegetable?.Length; // => null
Neste exercício, você vai escrever código para imprimir crachás de identificação para funcionários de uma fábrica.
Os funcionários têm um ID, um nome e o nome do departamento. O rótulo do crachá de um funcionário tem o seguinte formato: "[id] - name - DEPARTMENT". Implemente o método (static) Badge.Print() para retornar o rótulo do crachá de um funcionário:
Badge.Print(734, "Ernest Johnny Payne", "Strategic Communication");
// => "[734] - Ernest Johnny Payne - STRATEGIC COMMUNICATION"
Repare que o departamento deve aparecer em maiúsculas no rótulo.
Por causa de uma peculiaridade do sistema, às vezes os funcionários novos ainda não têm um ID quando começam a trabalhar na fábrica. Como o crachá é obrigatório, eles recebem um crachá temporário sem o prefixo do ID. Modifique o método (static) Badge.Print() para aceitar funcionários novos que ainda não têm um ID:
Badge.Print(id: null, "Jane Johnson", "Procurement");
// => "Jane Johnson - PROCUREMENT"
Até o dono da fábrica precisa usar um crachá o tempo todo. No entanto, o dono não tem um departamento. Nesse caso, o rótulo deve imprimir "OWNER" no lugar do nome do departamento. Modifique o método (static) Badge.Print() para imprimir o rótulo do dono:
Badge.Print(254, "Charlotte Hale", department: null);
// => "[254] - Charlotte Hale - OWNER"
Repare que é possível que o dono também seja um funcionário novo:
Badge.Print(id: null, "Charlotte Hale", department: null);
// => "Charlotte Hale - OWNER"
Crie sua conta no Exercism para aprender e dominar C# com 62 conceitos178 exercícios e mentoria humana de verdade, tudo de graça.