Es extraño incorrecto ridículo estúpido curioso que a los datos de tipo int
, string,
char
, byte
, float
, double
, etc. no se les pueda asignar un valor nulo. Esto no sería de importancia para nosotros si no fuera porque en C#, siempre debemos darle un valor a toda variable al ser inicializada, ya sea utilizando el constructor de su clase o, como solemos hacer para solventar este problema, inicializarla con valor nulo. ¿Pero qué hacemos si la clase no nos permite asignar este valor? Muy fácilmente nos toparemos con este problema mientras programamos, pero existe una solución.
Todos estos «tipos de datos» son un atajo (alias) a una clase del namespace System
.
- string: System.String
- char: System.Char
- byte: System.Byte
- short: System.Int16
- int: System.Int32
- long: System.Int64
- double: System.Double
- float: System.Single
- enum: Enum
Al ser todos clases, heredan en última instancia de la clase Object
. Aquí está lo extraño incorrecto ridículo estúpido curioso, pues, un objeto object
(válgame la redundancia) sí puede ser nulo. Pero bueno. El punto es que, al ser clases, todas tienen funciones y propiedades específicas para su funcionamiento, y aunque el lenguaje nos prohiba hacer una igualación a null
, sí nos permite realizar comparaciones para estos tipos.
MinValue
Para la mayoría de los tipos, existe la propiedad MinValue
.
int entero1 = 0; int entero2; float flotante1, flotante2 = 10.4f, flotante3; DateTime dt;
Las variables entero1 y flotante2 tienen un valor asignado desde su declaración. El resto de las variables no, por lo que de momento sus valores serán:
- entero2 = Int32.MinValue ó int.MinValue
- flotante2 y flotante3 = Single.MinValue ó float.MinValue
- dt = DateTime.MinValue
MinValue se utiliza para los tipos int, short, byte, long, char, DateTime, float, decimal, double y similares, así como uint, ulong, ushort, etc.
También está la propiedad MaxValue
, que indica el valor máximo permitido para estos tipos de dato de estos.
///<summary> ///<p>Lo sé, qué propósito tiene esta función? Sólo uno: servir de ejemplo xD</p> ///<summary> public int LongToInt(long valor){ if (valor == Int64.MinValue) throw new Exception("No se ha definido el valor."); elseif (valor > Int32.MaxValue) throw new Exception("No se puede. El valor es muy grande."); else return Convert.ToInt32(valor); }
El caso de las variables String
Debo confesar que este tipo de dato me confunde mucho. Hice varias pruebas: declarando una variable string con valor null me dio error; cambié el tipo de dato string por String y no me dio error; creé una segunda variable con tipo String y sí me dio error; borré todo, creé variables string y String diferentes, todas nulas, y no me dio error. Conclusión: no sé qué demonios pasa con esta clase!
En fin. La clase String tiene una propiedad Empty
, que en realidad nos trae una cadena de texto vacía. Yo acostumbro usarla cuando quiero limpiar una variable, aunque eso no es necesario, supongo.
string texto1 = String.Empty;
Para hacer comparaciones (que es en lo que siempre me falla, el tratar de comparar con null), lo más práctico es usar la función IsNullOrEmpty
de esta clase.
public void ImprimirTexto(string texto){ if (String.IsNullOrEmpty(texto)) throw new Exception("El texto está vacío o nulo."); Console.Write(texto); }
IsNullOrEmpty devuelve un valor verdadero si la variable está vacía («» o String.Empty) ó si no ha sido inicializada.
Enumeradores
Manipular enumeradores (enum) puede ser algo confuso al principio, pero no es difícil. La clase Enum
tiene la propiedad IsDefined
, que determina, obviamente, si se le ha dado un valor a la variable.
enum Enumerador{ uno, dos, tres } public void Metodo(Enumerador e){ if (Enum.IsDefined(typeof(Enumerador), e){ // Hacer cosas con el enumerador } else throw new Exception("No se ha definido el enumerador."); }
Los parámetros para el método IsDefined son el tipo del enumerador y la variable a evaluar.
Y sobre el tipo bool…
sinceramente, no tengo la menor idea. El tipo bool, alias de la clase System.Boolean, no tiene una propiedad para definir la variable con valor nulo.
He buscado mucho sobre Boolean, pero no encuentro nada. Sin embargo, hay otra forma con la que sí podemos asignar un valor null a esto tipos de dato:
Nullable types
Existe una variante para cada tipo de dato común que sí nos permite asignar el valor null. No conozco una traducción real, así que los llamaremos «nulables».
Los tipos nulables se definen exactamente como los normales, a excepción del signo ?
al final del nombre del tipo.
int? entero1 = null; int? entero2 = 4; double? doble = null; bool? boleanoNulo = null; entero2 = null; if (doble == null) throw new Exception("Es nulo.");
Ahora sí podemos tener cualquier tipo de dato nulo. Además, Todos estos tipos de dato cuentan con dos propiedades especiales:
- HasValue: Determina si se asignó un valor a esta variable.
- Value: Devuelve el valor en el tipo de dato «normal» de la variable.
///<summary> ///<p>Otra función sin sentido que nomás sirve de ejemplo.</p> ///</summary> public int ValorQuePuedeSerNuloAEntero(int? valorQuePuedeSerNulo){ if (valorQuePuedeSerNulo.HasValue) return valorQuePuedeSerNulo.Value; else throw new Exception("Sí, el valor es nulo."); }
Una variable de tipo nulable no es compatible con una de tipo normal. Para eso existe su propiedad Value.
En VB.NET, se utiliza la palabra Nullable
para estos tipos especiales
Dim var1 As Nullable Integer
Todas las funciones y propiedades de estas clases y las mencionadas al principio &son iguales en VB, pues son del framework, no del lenguaje.
Agradezco mucho por la información. He estado buscando lo mimo que menciona usted aquí. La verdad es que es estúpido que no dejen hacer que estas variables sean null cuando sea necesario >__>
De verdad que muchas gracias.
tambien se puede enviar null agregando el signo ? despues del tipo de variables de tipo
public void function(int? numero)
{
if (numero.HasValue())
{
//hacer cosas
}
}
Claro, Isaac. Lo menciono bajo el título Nullable types. Gracias 🙂
Y por cierto, tienes un error en el ejemplo. HasValue es una propiedad, no un método. No lleva paréntesis.
como podría sobreescribir una variable para que de tener un valor, pase a ser nula o vacía?
tengo este problema con variables float, int, y char.
Directamente a un float, int o char, no se puede. Tiene que ser de tipo Nullable, como expliqué en la última parte del artículo.
int? entero;
float? flotante;
char? caracter;