Qué problema resuelven?
Como todos saben a esta altura los value type (structs) no admiten como valor null, esto quire decir que si nosotros declaramos una variable de tipo int por ejemplo nunca vamos a poder una comparación por null ya que dicha variable no admite null como valor. Una posible solución elegante a este problema seria definir nuestra propia estructura entero que si soporte valores null como hice yo en el ejemplo a continuación.
public struct Entero
{
private int _valor;
private bool _tieneValor;
public Entero(int valor)
{
_valor = valor;
_tieneValor = true;
}
public int Valor
{
get
{
if (!_tieneValor)
throw new InvalidOperationException("No se ha definido un valor para esta variable");
return _valor;
}
set
{
_valor = value;
_tieneValor = true;
}
}
public bool TieneValor
{
get { return _tieneValor; }
}
public static implicit operator Entero(int valor)
{
return new Entero(valor);
}
public static Entero Null
{
get { return new Entero(); }
}
}
Como podemos ver basicamente agregue dos propiedades a la estructura, una que nos indica la precia de valor o no y la otra el valor en si mismo. De esta manera la consulta a esta estructura seria algo así.
static void Main(string[] args)
{
Entero variable = 3;
Entero variable2 = Entero.Null;
Console.WriteLine(variable.TieneValor? variable.Valor.ToString() : "null");
Console.WriteLine(variable2.TieneValor ? variable2.Valor.ToString() : "null");
Console.ReadKey();
}
Ahora si todo muy lindo pero esto para nosotros tiene un costo altísimo, si bien esta estructura es bastante sencilla cada vez que nos ponemos a reinventar la rueda corremos el riesgo que nos quede algo cuadrada. Ahi es donde viene el Framework a salvarnos definiendo un tipo de dato Nullable, que quiere decir esto? que acepta valores null.
Como definir los tipos Nullables?
Bueno basicamente la forma de definir que nuestro tipo de dato va a soportar null es agregando el operador ? al tipo de dato que estamos especificando. De esta manera las declaración que hice recién nos quedaran así.
static void Main(string[] args)
{
int? vari = 3;
int? vari2 = null;
Console.WriteLine(vari.HasValue ? vari.Value.ToString() : "null");
Console.WriteLine(vari2.HasValue ? vari2.Value.ToString() : "null");
Console.ReadKey();
}
Ahora lo que podemos ver es que la utilización es muy parecida a lo que habíamos definido anteriormente con lo cual lo que nos estamos ahorrando es la necesidad de crear nuestro propio tipo de datos para soportar valores null. Por otro lado al utilizar valor Nullables podemos hacer uso del operador que estuvimos viendo hace unas entradas el ?? ya que Nullable<T> nos ofrece varios métodos para hacer uso de esto como podemos ver a continuación.
static void Main(string[] args)
{
int? vari = 3;
int valor = 0;
valor = vari.HasValue ? vari.Value : 7;
valor = vari.GetValueOrDefault(7);
valor = vari ?? 7;
Console.WriteLine(vari2.HasValue ? vari2.Value.ToString() : "null");
Console.ReadKey();
}
Con cualquiera de las tres opciones que mostré anteriormente podemos ver que dependiendo del valor de la variable vamos a asignar el valor que tenga o en su defecto otro valor (o valor por defecto).
Ahora luego que vimos como funciona esta clase podemos decir con seguridad cuales son sus beneficios a la hora de trabajar con variables que podrían recibir valores null para comprarlas, manipularlas y hasta como acceder a su valor. De esta manera la respuesta a esta pregunta es que variables que soportan como valor null y que nos dejan manipularlo para poder acceder al valor de la misma.
No hay comentarios:
Publicar un comentario