domingo, 21 de octubre de 2018

Coalesce C#

En programación es bastante común que se compruebe si una variable "tiene valor" y si es así, se utiliza, y en caso contrario se usa un valor predeterminado.

Por ejemplo:

int rolActual;
if (rolUsuario != 0){
    rolActual = rolUsuario;
} else {
    rolActual = ROL_DEFAULT;
}

Podemos utilizar el operador condicional para este tipo de operaciones:

int rolActual = rolUsuario != 0 ? rolUsuario : ROL_DEFAULT;

Supongamos, que si el usuario no tiene rol asignado, comprobamos el rol de su grupo, y si tampoco está asignado, utilizamos un valor por defecto:

int rolActual;

if (rolUsuario != 0){
    rolActual = rolUsuario;
} else if (rolGrupo != 0)
    rolActual = rolGrupo;
} else {
    rolActual = ROL_DEFAULT;
}

Si utilizamos el operador condicional, sería así:

int rolActual = rolUsuario != 0 ? rolUsuario : (rolGrupo != 0 ? rolGrupo : ROL_DEFAULT);

Al añadir una segunda comprobación, es más difícil la lectura de esta expresión.

Como vemos, conforme aumenta el número de variables a comprobar, la legibilidad del código es peor. El operador condicional aquí no es una solución.

El estándar SQL-92 define la función COALESCE(), que admite un número de parámetros variable y devuelve el primer valor no nulo de los parámetros que se le pasan.

Podemos reproducir este comportamiento creando un método que admita un número variable de argumentos. Para ésto, utilizamos la palabra clave "params".

En lugar de valores nulos, vamos a considerar que una variable int está vacía si tiene valor cero. (Podríamos hacerlo con nulos, pero no es el caso que buscamos).

public static int Coalesce(params int[] integers)
{
    for (int i = 0; i < integers.Length; i++)
    {
        if (integers[i] != 0)
        {
            return integers[i];
        }
    }
    return 0;
}

La función va iterando por el array de valores que recibe, y devuelve el primero que no sea cero. Si no encuentra ninguno (todos los valores que recibe son cero),  devolverá cero.

Utilizando este método, la expresión anterior quedaría así:

int rolActual = Coalesce(rolUsuario, rolGrupo, ROL_DEFAULT);

El código es más legible y tiene la ventaja podemos utilizar tantos valores como queramos.

En el ejemplo, el último parámetro será el valor por defecto que queremos que tome rolActual, en el caso de que rolUsuario y rolGrupo "estén vacíos" (tengan valor cero).

Como la función recibe los valores de los parámetros en un array, podemos simplificar la función utilizando el método Enumerable.FirstOrDefault() que pertenece a System.Linq.

public static int Coalesce(params int[] integers)
{
    return integers.FirstOrDefault(i => i != 0);
}

Por supuesto, no tenemos que limitarnos a valores enteros. Podemos utilizar el mismo método para cualquier tipo de variable. Por ejemplo con cadenas de texto:

static string Coalesce(params string[] strings)
{
    return strings.FirstOrDefault(s => !string.IsNullOrEmpty(s)) ?? string.Empty;
}

Si todos los valores que recibe son null o cadenas vacías, el método FirstOrDefault() devolvería null, que es el valor por defecto del tipo string.

En este método, usamos el operador ?? para que el método, devuelva una cadena vacía.

Un ejemplo:
string texto1 = null;
string texto2 = string.Empty;
string texto3 = "Contenido";
string texto4 = null;

string resultado = Colaesce(texto1, texto2, texto3, texto4);

A la variable resultado se le asignará el valor de texto3  ("Contenido") que es la primera cadena de texto no vacía ni nula.

No hay comentarios:

Publicar un comentario

Coalesce C#

En programación es bastante común que se compruebe si una variable "tiene valor" y si es así, se utiliza, y en caso contrario se u...