Compartir a través de


Utilizar tipos que aceptan valores NULL (Guía de programación de C#)

Actualización: noviembre 2007

Los tipos que aceptan valores NULL pueden representar todos los valores de un tipo subyacente y un valor null adicional. Los tipos que aceptan valores NULL se declaran de dos formas:

System.Nullable<T> variable

O bien

T? variable

T es el tipo subyacente del tipo que acepta valores NULL. T puede ser cualquier tipo de valor, incluso struct; no puede ser un tipo de referencia.

Para obtener un ejemplo de cuándo se podría utilizar un tipo que acepta valores NULL, piense en una variable booleana común que puede tener dos valores: true y false. No hay ningún valor que signifique "indefinido". En muchas aplicaciones de programación, en particular en las interacciones de bases de datos, pueden existir variables con un estado indefinido. Por ejemplo, un campo de una base de datos puede contener los valores true o false, pero también puede que no contenga ningún valor. Igualmente, los tipos de referencia se pueden establecer en null para indicar que no se inicializan.

Esta disparidad puede crear trabajo de programación extra, con variables adicionales que se utilizan para almacenar información de estado, el uso de valores especiales, etc. El modificador de tipos que aceptan valores NULL permite a C# crear variables de tipo de valor que pueden indicar un valor indefinido.

Ejemplos de tipos que aceptan valores NULL

Cualquier tipo de valor se puede utilizar como base para un tipo que acepta valores NULL. Por ejemplo:

int? i = 10;
double? d1 = 3.14;
bool? flag = null;
char? letter = 'a';
int?[] arr = new int?[10];

Miembros de tipos que aceptan valores NULL

Cada instancia de un tipo que acepta valores NULL tiene dos propiedades públicas de sólo lectura:

  • HasValue

    HasValue es de tipo bool. Se establece como true cuando la variable contiene un valor que no es null.

  • Value

    Value es del mismo tipo que el tipo subyacente. Si HasValue es true, Value contiene un valor significativo. Si HasValue es false, al tener acceso a Value se producirá una excepción InvalidOperationException.

En este ejemplo, el miembro HasValue se utiliza para comprobar si la variable contiene un valor antes de mostrarlo.

int? x = 10;
if (x.HasValue)
{
    System.Console.WriteLine(x.Value);
}
else
{
    System.Console.WriteLine("Undefined");
}

La comprobación de un valor también puede realizarse tal y como se muestra en el siguiente ejemplo:

int? y = 10;
if (y != null)
{
    System.Console.WriteLine(y.Value);
}
else
{
    System.Console.WriteLine("Undefined");
}

Conversiones explícitas

Un tipo que acepta valores NULL se puede convertir en un tipo normal mediante el uso explícito de la conversión o a través de la propiedad Value. Por ejemplo:

int? n = null;

//int m1 = n;      // Will not compile.
int m2 = (int)n;   // Compiles, but will create an exception if x is null.
int m3 = n.Value;  // Compiles, but will create an exception if x is null.

Si se define una conversión definida por el usuario entre dos tipos de datos, la misma conversión se puede utilizar con las versiones que aceptan valores NULL de estos tipos de datos.

Conversiones implícitas

Una variable de tipo que acepta valores NULL puede establecerse como null con la palabra clave null, tal y como se muestra en el siguiente ejemplo:

int? n1 = null;

La conversión de un tipo ordinario a un tipo que acepta valores NULL, es implícita.

int? n2;
n2 = 10;  // Implicit conversion.

Operadores

Los operadores predefinidos unarios y binarios así como cualquier operador definido por el usuario que exista para los tipos de valor también pueden ser utilizados por los tipos que aceptan valores NULL. Estos operadores generan un valor null si los operandos son null; de lo contrario, el operador utiliza el valor contenido para calcular el resultado. Por ejemplo:

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

a++;         // Increment by 1, now a is 11.
a = a * 10;  // Multiply by 10, now a is 110.
a = a + b;   // Add b, now a is null.

Al realizar comparaciones con tipos que aceptan valores null, si alguno de estos tipos es null, la comparación siempre se evalúa como false. Por consiguiente, es importante no dar por supuesto que, porque una comparación sea false, el caso contrario será true. Por ejemplo:

int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
    System.Console.WriteLine("num1 is greater than or equal to num1");
}
else
{
    // num1 is NOT less than num2
}

La conclusión en la instrucción else no es válida porque num2 es null y, por lo tanto, no contiene ningún valor.

Una comparación de dos tipos que aceptan valores null y ambos son null se evaluará como true.

El operador ??

El operador ?? define un valor predeterminado que se devuelve cuando un tipo que acepta valores NULL se asigna a un tipo que no acepta valores NULL.

int? c = null;

// d = c, unless c is null, in which case d = -1.
int d = c ?? -1;

Este operador también se puede utilizar con muchos tipos que no aceptan valores NULL. Por ejemplo:

int? e = null;
int? f = null;

// g = e or f, unless e and f are both null, in which case g = -1.
int g = e ?? f ?? -1;

El tipo bool?

El tipo bool? que acepta valores NULL, puede contener tres valores diferentes: true, false y null. Para obtener información sobre cómo convertir un tipo bool? en un tipo un bool, consulte Cómo: Convertir con seguridad de bool? en bool (Guía de programación de C#).

Los tipos booleanos que aceptan valores NULL son como el tipo de variable booleano que se utiliza en SQL. Para asegurarse de que los resultados producidos por los operadores & y | sean coherentes con el tipo booleano de tres valores de SQL, se proporcionan los siguientes operadores predefinidos:

bool? operator &(bool? x, bool? y)

bool? operator |(bool? x, bool? y)

Los resultados de estos operadores se muestran en la siguiente tabla:

X

y

x&y

x|y

true

true

true

true

true

false

false

true

true

null

null

true

false

true

false

true

false

false

false

false

false

null

false

null

null

true

null

true

null

false

false

null

null

null

null

null

Vea también

Conceptos

Guía de programación de C#

Referencia

Tipos que aceptan valores NULL (Guía de programación de C#)

Aplicar la conversión boxing a tipos que aceptan valores NULL (Guía de programación de C#)