Comprobar si una variable de tipo string está vacía es una
tarea que seguro realizamos muy a menudo en nuestras aplicaciones. Observando
código, tanto propio como ajeno, he visto que existen varias formas de hacerlo,
y a veces cometemos errores que pueden ser fácilmente evitables prestando un
poco de atención.
Por ejemplo, dada una variable str declarada
como string, utilizando en C# la expresión str.Equals("")
podemos conocer si str contiene una cadena vacía. Sin embargo, si
str contiene un valor nulo (lo cual es perfectamente posible al
tratarse de un tipo referencia) se provocará una excepción de tipo
System.NullReferenceException
, puesto que estamos intentando llamar
a un método de un objeto inexistente.
Ocurre lo mismo si intentamos
averiguar el número de caracteres que contiene: (str.Length==0)
es
cierto si la cadena está vacía, pero igualmente revienta si se trata de un valor
nulo.
Una posible solución es preguntar previamente si la cadena es nula
y sólo en caso contrario preguntar, siguiendo alguno de los dos patrones
descritos anteriormente, si se trata de un string vacío, algo así:
.
((str!=null) && (str.Length==0))
Como podéis
observar, aunque válido, parece demasiado laborioso para los que tenemos prisa.
Otra forma más corta e ingeniosa de poner lo mismo sería la siguiente:
"".Equals(str)
. Como podéis ver, el problema del nulo desaparece,
puesto que se llama al método Equals de la cadena constante "" que
siempre tiene valor (la cadena vacía).
Sin embargo, cualquiera de los
casos anteriormente citados pueden no funcionar correctamente si consideramos
los nulos como una forma más de expresar una cadena vacía. Por ejemplo, observad
el siguiente código:
private string saludar(string nombre)
{
if ("".Equals(nombre))
return "No saludo a nadie";
else
return "Hola, " + nombre;
}
La función retorna el literal "No saludo a nadie" cuando le llega un nombre vacío (""). Sin embargo, si le llega un valor nulo no se cumple la primera igualdad, entraría en el bloque else y retornaría un saludo absurdo, "Hola, ". Y es que hay veces donde semánticamente el nulo y la cadena vacía son idénticos.
Para estos casos es conveniente hacer equivalentes ambos valores, de forma que nuestra función se comporte exactamente igual tanto si recibe un nulo como si le llega un string vacío. Veamos algunas formas de conseguirlo.
Una fórmula que he visto alguna vez consiste en sumar a nuestro string una cadena vacía en algún momento del proceso, es decir, usar algo como:
""+str
. Esta expresión devolverá siempre
un string vacío o con el valor original de la variable str, pero nunca
un nulo. Una vez realizada esta operación, podemos hacer la comparación con
.Equals("")
o .Length==0
, aunque se recomienda este
último por su mejor rendimiento.Otra forma, algo mejor que la anterior, es usar dos comparaciones combinadas con OR:
((str == null) ||
(str.Equals(String.Empty)))
. Así, si str es nulo la expresión
evalúa a cierto y sólo en caso contrario se realizará la comparación con la
cadena vacía (String.Empty es lo mismo que el string "").Pero sin duda la mejor opción sería usar el método estático introducido en la clase string en la versión 2.0 de la plataforma:
string.IsNullOrEmpty()
. Siguiendo con el ejemplo
anterior, podríamos reescribirlo de la siguiente manera, consiguiendo el efecto
deseado:
private string saludar(string nombre)
{
if (string.IsNullOrEmpty(nombre))
return "No saludo a nadie";
else
return "Hola, " + nombre;
}
Este sería un buen momento para dar por finalizado el post si no fuera por que existe un inconveniente a este método, algo que puede parecer increíble: en el framework de Microsoft IsNullOrEmpty() puede hacer que tu aplicación reviente en tiempo de ejecución en las versiones de producción (release) de los ensamblados debido a una mala optimización del JIT cuando utilizamos este método dentro de un bucle. No daré más detalles pues hay multitud de páginas hablando del problema (como VTortola, o El Bruno), pero aquí se aconsejan alternativas a utilizar. En fin, que este método, según se lee, debe ser usado con precaución, o incluso evitado si lo pensamos incluir en un bucle.
Llegados a este punto, por tanto, lo aconsejable es quedarnos con fórmulas artesanales como
((str ==
null)||(str.Length==0)
, hasta que IsNullOrEmpty esté en
condiciones de ser utilizado, podemos suponer que en la próxima versión de la
plataforma. No he comprobado si existe el mismo problema sobre la plataforma Mono, pero dado que son implementaciones distintas lo más probable es que no ocurra, por lo que IsNullOrEmpty podría ser utilizado sin causar dolores de cabeza. A ver si un día tengo un ratillo y lo compruebo.
Hay que ver lo que da de sí una cosa tan simple, ¿eh?
Publicado por José M. Aguilar a las 9:00 PM
Etiquetas: .net, c#, desarrollo, nivel básico, programación, trucos
2 Comentarios:
Hola José,
Excelente el post como de costumbre. Yo creo que este tipo de cosas son las que diferencian a los grandes desarrolladores del promedio, ya que demuestran un interés por el detalle, un conocimiento más fino de la herramienta, y hacen que el resultado final sea una aplicación de mayor calidad, solidez y rendimiento. Gracias por otro excelente aporte a la comunidad de habla hispana.
Comentarios así son los que hacen que todo esto valga la pena. :-)
Muchas gracias, Leonardo.
Enviar un nuevo comentario
Backlinks:
¡Bloguea sobre este tema!