Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Un tipo de valor que admite un valor NULLT? representa todos los valores de su tipo de valor subyacente T y un valor NULL adicional. Por ejemplo, puede asignar cualquiera de los tres valores siguientes a una variable bool?: true, false o null. Un tipo T de valor subyacente no puede ser un tipo de valor que acepta valores NULL.
La referencia del lenguaje C# documenta la versión publicada más recientemente del lenguaje C#. También contiene documentación inicial sobre las características de las versiones preliminares públicas de la próxima versión del lenguaje.
La documentación identifica cualquier característica introducida por primera vez en las últimas tres versiones del idioma o en las versiones preliminares públicas actuales.
Sugerencia
Para buscar cuándo se introdujo por primera vez una característica en C#, consulte el artículo sobre el historial de versiones del lenguaje C#.
Todos los tipos que admiten valores NULL son instancias de la estructura System.Nullable<T> genérica. Puede hacer referencia a un tipo de valor que admite valores NULL con un tipo subyacente T en cualquiera de las formas intercambiables siguientes: Nullable<T> o T?.
Normalmente, use un tipo de valor que acepta valores NULL cuando necesite representar el valor indefinido de un tipo de valor subyacente. Por ejemplo, una variable booleana, o bool, solo puede ser true o false. Sin embargo, en algunas aplicaciones, un valor de variable puede estar sin definir o faltar. Por ejemplo, un campo de base de datos puede contener true o false, o puede que no contenga ningún valor, es decir, NULL. Puede usar el tipo bool? en ese escenario.
Declaración y asignación
Dado que un tipo de valor se puede convertir implícitamente en el tipo de valor que acepta valores NULL correspondiente, puede asignar un valor a una variable de un tipo de valor que acepta valores NULL tal como lo hace para su tipo de valor subyacente. También se puede asignar el valor null. Por ejemplo:
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];
El valor predeterminado de un tipo de valor que acepta valores NULL representa null. Es una instancia cuya Nullable<T>.HasValue propiedad devuelve false.
Examen de una instancia de tipo de valor que admite valores NULL
Para comprobar una instancia de un tipo null de valor que acepta valores NULL y obtener un valor de un tipo subyacente, use el is operador con un patrón de tipo:
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
Siempre puede usar las siguientes propiedades de solo lectura para comprobar y obtener un valor de una variable de tipo de valor que acepta valores NULL:
Nullable<T>.HasValue muestra si una instancia de un tipo de valor que acepta valores NULL tiene un valor de su tipo subyacente.
Nullable<T>.Value obtiene el valor de un tipo subyacente si HasValue es
true. Si HasValue esfalse, la propiedad Value inicia una excepción InvalidOperationException.
En el ejemplo siguiente se usa la HasValue propiedad para comprobar si la variable contiene un valor antes de mostrarla:
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
También se puede comparar una variable de un tipo de valor que admite valores NULL con null en lugar de usar la propiedad HasValue, como se muestra en el ejemplo siguiente:
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
Conversión de un tipo de valor que admite un valor NULL a un tipo subyacente
Si desea asignar un valor de un tipo de valor que acepta valores NULL a una variable de tipo de valor que no acepta valores NULL, es posible que tenga que especificar el valor que se va a asignar en lugar de null. Use el operador ??de fusión null para hacerlo. También puede usar el Nullable<T>.GetValueOrDefault(T) método para el mismo 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
Si desea utilizar el valor predeterminado del tipo de valor subyacente en lugar de null, use el método Nullable<T>.GetValueOrDefault().
También puede convertir de forma explícita un tipo de valor que admite valores NULL en uno que no los admite, como se indica en el ejemplo siguiente:
int? n = null;
//int m1 = n; // Doesn't compile
int n2 = (int)n; // Compiles, but throws an exception if n is null
En tiempo de ejecución, si el valor de un tipo de valor que admite un valor NULL es null, la conversión explícita inicia una InvalidOperationException.
Un tipo de valor que no admite valores NULL T se convierte implícitamente al tipo que admite valores NULL T? correspondiente.
Operadores de elevación
Un tipo T? de valor que acepta valores NULL admite los operadores unarios y binarios predefinidos o los operadores sobrecargados que admite un tipo T de valor. Estos operadores, también conocidos como operadores de elevación, devuelven null si uno o ambos operandos son null. De lo contrario, el operador usa los valores contenidos de sus operandos para calcular el resultado. Por ejemplo:
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 el tipo bool?, los operadores predefinidos & y | no siguen las reglas descritas en esta sección: el resultado de una evaluación de operador puede ser distinto de NULL incluso si uno de los operandos es null. Para más información, consulte la sección Operadores lógicos booleanos que aceptan valores NULL del artículo Operadores lógicos booleanos.
Para los operadores< de comparación, >, <=y >=, si uno o ambos operandos son null, el resultado es false. De lo contrario, se comparan los valores contenidos de los operandos. No suponga que, dado que una comparación determinada (por ejemplo, <=) devuelve false, la comparación opuesta (>) devuelve true. En el ejemplo siguiente se muestra que 10 no es
- mayor ni igual que
null, - ni es menor que
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 el operador== de igualdad, si ambos operandos son null, el resultado es true. Si solo uno de los operandos es null, el resultado es false. De lo contrario, se comparan los valores contenidos de los operandos.
Para el operador!= de desigualdad, si ambos operandos son null, el resultado es false. Si solo uno de los operandos es null, el resultado es true. De lo contrario, se comparan los valores contenidos de los operandos.
Si existe una conversión definida por el usuario entre dos tipos de valor, también se puede usar la misma conversión entre los tipos de valor que aceptan valores NULL correspondientes.
Conversión boxing y conversión unboxing
Las reglas siguientes se aplican cuando se boxe una instancia de un tipo T?de valor que acepta valores NULL:
- Si HasValue devuelve
false, la operación boxing devuelve la referencia nula. - Si HasValue devuelve
true, los cuadros de operación de conversión boxing son el valor correspondiente del tipoTde valor subyacente , no la instancia de Nullable<T>.
Se puede aplicar conversión unboxing a un tipo de valor T con conversión boxing al tipo T? que acepta valores NULL correspondiente, como se muestra en el ejemplo siguiente:
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
Identificación de tipos que admiten valores NULL
El ejemplo siguiente muestra cómo determinar si una instancia System.Type representa un tipo de valor construido que admite valores NULL, es decir, el tipo System.Nullable<T> con un parámetro de tipo especificado T:
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 se muestra en el ejemplo, se usa el operador typeof para crear una instancia System.Type.
Si desea determinar si una instancia es de un tipo de valor que acepta valores NULL, no use el Object.GetType método para obtener una Type instancia para probar mediante el código anterior. Cuando se llama al método Object.GetType en una instancia de un tipo de valor que admite un valor NULL, se aplica la conversión boxing a la instancia para convertirla en Object. Dado que la conversión boxing de una instancia que no es NULL de un tipo de valor que acepta valores NULL equivale a la conversión boxing de un valor boxing del tipo subyacente, GetType devuelve una Type instancia que representa el tipo subyacente de un tipo de valor que acepta valores NULL:
int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:
// System.Int32
No use el operador is para determinar si una instancia es de un tipo de valor que admite valores NULL. Como se muestra en el ejemplo siguiente, no se pueden distinguir los tipos de una instancia de tipo de valor que acepta valores NULL y su instancia de tipo subyacente mediante el 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?
En su lugar, use el Nullable.GetUnderlyingType método del primer ejemplo y el operador typeof para comprobar si una instancia es de un tipo de valor que acepta valores NULL.
Nota
Los métodos descritos en esta sección no se aplican a los tipos de referencia que aceptan valores NULL.
Especificación del lenguaje C#
Para más información, vea las secciones siguientes de la Especificación del lenguaje C#:
- Nullable types (Tipos que aceptan valores NULL [Guía de programación de C#])
- Operadores de elevación
- Conversiones implícitas que aceptan valores NULL
- Conversiones explícitas que aceptan valores NULL
- Operadores de conversión de elevación