Partilhar via


Tipos de valor anulável (referência C#)

Um de valor anulável representa todos os valores de seu tipoT?e um valor nulo adicional. Por exemplo, você pode atribuir qualquer um dos três valores a seguir a uma bool? variável: true, false, ou null. Um tipo T de valor subjacente não pode ser, por si só, um tipo de valor nulo.

A referência da linguagem C# documenta a versão mais recentemente lançada da linguagem C#. Contém também documentação inicial para funcionalidades em pré-visualizações públicas para o próximo lançamento linguístico.

A documentação identifica qualquer funcionalidade introduzida pela primeira vez nas últimas três versões da língua ou em pré-visualizações públicas atuais.

Sugestão

Para saber quando uma funcionalidade foi introduzida pela primeira vez em C#, consulte o artigo sobre o histórico de versões da linguagem C#.

Qualquer tipo de valor anulável é uma instância da estrutura genérica System.Nullable<T> . Você pode fazer referência a um tipo de valor anulável com um tipo T subjacente em qualquer uma das seguintes formas intercambiáveis: Nullable<T> ou T?.

Normalmente, usa um tipo de valor nulo quando precisas de representar o valor indefinido de um tipo subjacente. Por exemplo, uma variável booleana, ou bool, só pode ser uma true ou false. No entanto, em alguns aplicativos, um valor de variável pode estar indefinido ou ausente. Por exemplo, um campo de base de dados pode conter true ou false, ou pode não conter qualquer valor, ou seja, NULL. Você pode usar o bool? tipo nesse cenário.

Declaração e cessão

Como um tipo de valor é implicitamente convertível para o tipo correspondente de valor nulo, pode atribuir um valor a uma variável de um tipo de valor nulo tal como faz para o seu tipo de valor subjacente. Você também pode atribuir o null valor. Por exemplo:

double? pi = 3.14;
char? letter = 'a';

int m2 = 10;
int? m = m2;

bool? flag = null;

// An array of a nullable value type:
int?[] arr = new int?[10];

O valor padrão de um tipo de valor anulável representa null. É uma instância cuja Nullable<T>.HasValue propriedade devolve false.

Exame de uma instância de um tipo de valor anulável

Para verificar uma instância de um tipo de valor nulo para null e obter um valor de um tipo subjacente, use o is operador com um padrão de tipos:

int? a = 42;
if (a is int valueOfA)
{
    Console.WriteLine($"a is {valueOfA}");
}
else
{
    Console.WriteLine("a does not have a value");
}
// Output:
// a is 42

Pode sempre usar as seguintes propriedades de só leitura para verificar e obter o valor de uma variável do tipo valor nulo:

O exemplo seguinte usa a HasValue propriedade para verificar se a variável contém um valor antes de a exibir:

int? b = 10;
if (b.HasValue)
{
    Console.WriteLine($"b is {b.Value}");
}
else
{
    Console.WriteLine("b does not have a value");
}
// Output:
// b is 10

Você também pode comparar uma variável de um tipo de valor anulável com null em vez de usar a HasValue propriedade, como mostra o exemplo a seguir:

int? c = 7;
if (c != null)
{
    Console.WriteLine($"c is {c.Value}");
}
else
{
    Console.WriteLine("c does not have a value");
}
// Output:
// c is 7

Conversão de um tipo de valor anulável para um tipo subjacente

Se quiser atribuir um valor de um tipo de valor nulo a uma variável do tipo de valor não anulável, pode ser necessário especificar o valor a atribuir em vez de null. Use o operador ??de coalescimento nulo para isso. Também pode usar o Nullable<T>.GetValueOrDefault(T) método para o mesmo propósito:

int? a = 28;
int b = a ?? -1;
Console.WriteLine($"b is {b}");  // output: b is 28

int? c = null;
int d = c ?? -1;
Console.WriteLine($"d is {d}");  // output: d is -1

Se você quiser usar o valor padrão do tipo de valor subjacente no lugar de null, use o Nullable<T>.GetValueOrDefault() método.

Você também pode converter explicitamente um tipo de valor anulável para um tipo não anulável, como mostra o exemplo a seguir:

int? n = null;

//int m1 = n;    // Doesn't compile
int n2 = (int)n; // Compiles, but throws an exception if n is null

Em tempo de execução, se o valor de um tipo de valor anulável for null, o cast explícito lançará um InvalidOperationExceptionarquivo .

Um tipo T de valor não anulável é implicitamente conversível para o tipo T?de valor anulável correspondente.

Operadores de elevadores

Um tipo T? de valor nulo suporta os operadores unários e binários predefinidos ou quaisquer operadores sobrecarregados que um tipo T de valor suporte. Estes operadores, também conhecidos como operadores elevados, retornam null se um ou ambos os operandos forem null. Caso contrário, o operador usa os valores contidos dos seus operandos para calcular o resultado. Por exemplo:

int? a = 10;
int? b = null;
int? c = 10;

a++;        // a is 11
a = a * c;  // a is 110
a = a + b;  // a is null

Nota

Para o bool? tipo, os operadores predefinidos & e | não seguem as regras descritas nesta seção: o resultado de uma avaliação do operador pode ser não-nulo, mesmo que um dos operandos seja null. Para obter mais informações, consulte a seção Operadores lógicos booleanos anuláveis do artigo Operadores lógicos booleanos.

Para os operadores <de comparação, >, <=, , e >=, se um ou ambos os operandos forem null, o resultado é false. Caso contrário, os valores contidos dos operandos são comparados. Não presuma que, porque uma comparação particular (por exemplo, <=) devolve false, a comparação oposta (>) devolve true. O exemplo a seguir mostra que 10 é

  • nem superior nem igual a null
  • nem inferior a null
int? a = 10;
Console.WriteLine($"{a} >= null is {a >= null}");
Console.WriteLine($"{a} < null is {a < null}");
Console.WriteLine($"{a} == null is {a == null}");
// Output:
// 10 >= null is False
// 10 < null is False
// 10 == null is False

int? b = null;
int? c = null;
Console.WriteLine($"null >= null is {b >= c}");
Console.WriteLine($"null == null is {b == c}");
// Output:
// null >= null is False
// null == null is True

Para o operador ==de igualdade, se ambos os operandos são null, o resultado é true. Se apenas um dos operandos for null, o resultado é false. Caso contrário, os valores contidos dos operandos são comparados.

Para o operador!= de desigualdade, se ambos os operandos são null, o resultado é false. Se apenas um dos operandos for null, o resultado é true. Caso contrário, os valores contidos dos operandos são comparados.

Se existir uma conversão definida pelo utilizador entre dois tipos de valor, a mesma conversão pode também ser usada entre os tipos correspondentes de valor nulo.

Boxe e unboxing

As seguintes regras aplicam-se quando se encaixa uma instância de um tipo T?de valor nulo :

  • Se HasValue devolver false, a operação de boxing devolve a referência nula.
  • Se HasValue devolve true, a operação de boxing encaixa o valor correspondente do tipo Tde valor subjacente , não a instância de Nullable<T>.

Você pode descompactar um valor em caixa de um tipo T de valor para o tipo T?de valor anulável correspondente, como mostra o exemplo a seguir:

int a = 41;
object aBoxed = a;
int? aNullable = (int?)aBoxed;
Console.WriteLine($"Value of aNullable: {aNullable}");

object aNullableBoxed = aNullable;
if (aNullableBoxed is int valueOfA)
{
    Console.WriteLine($"aNullableBoxed is boxed int: {valueOfA}");
}
// Output:
// Value of aNullable: 41
// aNullableBoxed is boxed int: 41

Como identificar um tipo de valor anulável

O exemplo a seguir mostra como determinar se uma System.Type instância representa um tipo de valor nulo construído, ou seja, o System.Nullable<T> tipo com um parâmetro Ttype especificado:

Console.WriteLine($"int? is {(IsNullable(typeof(int?)) ? "nullable" : "non nullable")} value type");
Console.WriteLine($"int is {(IsNullable(typeof(int)) ? "nullable" : "non-nullable")} value type");

bool IsNullable(Type type) => Nullable.GetUnderlyingType(type) != null;

// Output:
// int? is nullable value type
// int is non-nullable value type

Como mostra o exemplo, você usa o operador typeof para criar uma System.Type instância.

Se quiser determinar se uma instância é do tipo valor nulo, não use o Object.GetType método para fazer uma Type instância testar usando o código anterior. Quando você chama o Object.GetType método em uma instância de um tipo de valor anulável, a instância é encaixotada como Object. Como o boxing de uma instância não nula de um tipo de valor nulo é equivalente a boxing de um valor do tipo subjacente, GetType devolve uma Type instância que representa o tipo subjacente de um tipo de valor nulo:

int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:
// System.Int32

Além disso, não use o operador is para determinar se uma instância é de um tipo de valor anulável. Como mostra o exemplo seguinte, não se podem distinguir os tipos de uma instância de tipo valor anulável e a sua instância de tipo subjacente usando o is operador:

int? a = 14;
if (a is int)
{
    Console.WriteLine("int? instance is compatible with int");
}

int b = 17;
if (b is int?)
{
    Console.WriteLine("int instance is compatible with int?");
}
// Output:
// int? instance is compatible with int
// int instance is compatible with int?

Em vez disso, utilize-se o Nullable.GetUnderlyingType método do primeiro exemplo e o tipo de operador para verificar se uma instância é do tipo valor nulo.

Nota

Os métodos descritos nesta secção não se aplicam a tipos de referência anuláveis.

Especificação da linguagem C#

Para obter mais informações, consulte as seguintes seções da especificação da linguagem C#:

Consulte também