Una sinfonía en C#

Un pequeño aporte a la comunidad de habla hispana.

Delegate, predicate, Action, Func, métodos anónimos, explicados para mortales.

No es un tema nuevo ni mucho menos,  sin embargo no siempre es del todo bien comprendido y su correcta comprensión es muy importante ya que muchas otras características del framework se apoyan en los delegados, así que vamos a hablar un poco sobre ellos.

Pero, ¿Qué es un delegado?

La respuesta corta es “un delegado es una referencia a un método”, pero no confundir, no es una referencia como un puntero sino que en realidad un delegado nos permite definir una firma para poder luego pasar un método. Vemos un ejemplo.

var testDelegates = new TestDelegates();
testDelegates.DoSomething();

En este simple código tenemos un objeto testDelegates que tiene un método DoSomething y que hace algo, imaginemos que ese método, por ejemplo, hace una llamada a un servicio que ocurre de manera asíncrona y termina después de un tiempo indeterminado. La llamada se realiza pero queremos que de alguna manera este método nos informe que la ejecución ha finalizado. Bien, una forma de hacerlo sería indicarle a DoSomething  que luego de finalizar su ejecución invoque a otro método y nosotros hagamos algo en consecuencia. Más o menos cómo cuando hacemos una llamada AJAX desde Javascript donde tenemos una forma de ser informados de la finalización de la ejecución de la llamada.

Delegado simple

Para hacer esto necesitamos indicar a DoSomething cuál es el método que queremos que sea invocado al final su ejecución (exitosa o no, en este caso eso no nos preocupa) .NET nos permite hacer esto pero nos obliga de definir siempre la firma del método a ser llamado, es decir, tenemos de alguna manera que decir en DoSomething que podemos informar el final de la ejecución a un método pero con cierta firma (que reciba ciertos parámetros y devuelva cierto tipo de datos) acá es donde entran los delegados en acción, justamente nos permiten definir la firma del método.

public class TestDelegates
{
    // declaración del delegador, sin valor de retorno (void) y sin parámetros
    public delegate void DelegadoSimple();
    public void DoSomething(DelegadoSimple delegado)
    {
        // does something
        // llamar al la función
        delegado();
    }
}

Los primero que hacemos es definir el delegado de modo de que sea visible, como dijimos antes esta será la firma que deberá tener el método que pasaremos como parámetro, entonces lo ponemos en la clase que lo utilizará con visibilidad pública.

Luego ponemos como parámetro el delegado que funciona como un tipo y nos permite tener la referencia a la función.

Luego dentro del código podemos invocar la función, en este caso solo agregando los paréntesis porque no recibe parámetros.

private static void Main(string[] args)
{
    var testDelegates = new TestDelegates();
    testDelegates.DoSomething(FuncionSimple);
}

private static void FuncionSimple()
{
    // hacer algo
}

En cuando a la llamada a DoSomething simplemente agregamos el parámetro que es una función igual que el delegado, que no retorna valor (es void) y no recibe parámetros, notemos que no tiene parámetros porque no la invocamos solo pasamos una referencia.

Métodos anónimos

Qué pasaría si no quisiéramos crear una función con nombre y todo para que sea invocada. En este caso podemos crearla inline, de este modo:

private static void Main(string[] args)
{
    var testDelegates = new TestDelegates();
    // en este caso pasamos un método anónimo
    testDelegates.DoSomething(()=>
    {
        //hacer algo
    });
}

Lo que hicimos es declarar nuestro método en el mismo sitio que invocamos a DoSomething, vamos a analizar la sintaxis.

testDelegates.DoSomething(()=>
{
    //hacer algo
});

Primero tenemos que tenemos en cuenta que es necesario cumplir con el delegado, con lo cual el método anónimo no tiene valor de retorno y no recibe parámetros. entonces lo primero que vemos es que hay dos paréntesis vacíos, justamente porque no recibe parámetros y luego la “flecha” que indica que a continuación viene el cuerpo el método ()=>

Después simplemente tenemos las llaves que limitan el cuerpo del método anónimo y si tuviéramos código estaría por ahí, como el método no retorna valor no hay un return.

Es importante destacar que al ser anónimo (el método no tiene nombre) no puede ser invocado desde otra parte.

Imaginemos que lo que queremos hacer es escribir en la consola, el código quedaría así:

testDelegates.DoSomething(() =>
{
    Console.WriteLine("Ejecución finalizada");
});

Y qué ganamos creando un método anónimos? bien, lo principal es que es posible que no usemos ese método para nada más que para ser invocado por DoSomething, por otro lado tenemos visibilidad de las variables dentro del método donde declaramos el método anónimo, por ejemplo podemos hacer esto:

var testDelegates = new TestDelegates();
var variablePrivada = "valor original";
            // en este caso pasamos un método anónimo
testDelegates.DoSomething(() =>
{
    Console.WriteLine("Ejecución finalizada");
    Console.WriteLine($"El valor de la variable 'variablePrivada' es {variablePrivada}");
    variablePrivada = "valor nuevo";
    Console.WriteLine($"El nuevo valor de la variable 'variablePrivada' es {variablePrivada}");
});

No solamente podemos leer una variable privada del método donde declaramos el método anónimo sino que también podemos modificarla, algo similar a un closure.

Métodos anónimos con parámetros

public delegate void DelegadoSimple(int milisegundos);
public void DoSomething(DelegadoSimple delegado)
{
    // does something
    // llamar al la función
    delegado(20);
}

Primero cambiamos la definición del método anónimo para que reciba parámetros, en este caso el tiempo que demoró la ejecución de nuestro método DoSomething, esta vez cuando lo invocamos le pasamos el valor.

private static void Main(string[] args)
{
    var testDelegates = new TestDelegates();
    testDelegates.DoSomething(FuncionSimple);
}

private static void FuncionSimple(int milisegundos)
{
    Console.WriteLine("Ejecución finalizada");
    Console.WriteLine($"La ejecución tomó {milisegundos} milisegundos");
}

Modificamos el método para que reciba el parámetro y al ser ejecutada lo mostramos en pantalla, si lo hiciéramos anónimos sería así:

private static void Main(string[] args)
{
    var testDelegates = new TestDelegates();
    testDelegates.DoSomething((int milisegundos) =>
    {
        Console.WriteLine("Ejecución finalizada");
        Console.WriteLine($"La ejecución tomó {milisegundos} milisegundos");
    });
}

en este caso agregamos en parámetro dentro de los paréntesis.

¿Y qué pasa si tenemos que devolver valores en nuestros delegados?

Por supuesto que podemos tener un delegado que retorne un valor de cualquier tipo, un ejemplo sería el siguiente:

public delegate string DelegadoSimple(int milisegundos);
public void DoSomething(DelegadoSimple delegado)
{
    // does something
    // llamar al la función
    Console.Write(delegado(20));
}

Ahora cambiamos la declaración del delegado para que retorne un string y al invocar el delegado lo imprimimos, en código de la otra parte sería así:

testDelegates.DoSomething((int milisegundos) =>
{
    Console.WriteLine("Ejecución finalizada");
    return $"La ejecución tomó {milisegundos} milisegundos";
});

Muy sencillo.

Delegados predefinidos.

Existen algunos delegados predefinidos que nos permiten evitar declarar todo el tiempo los propios, lo más comunes son:

  • Predicate
  • Action
  • Func

El predicate se usa en muchos métodos de filtrado de colecciones, por ejemplo en la lista genérica:

public T Find(Predicate match)

Y si vemos la definición de predicate podemos comprender bien de qué se trata

public delegate bool Predicate(T obj)

Un predicate sirve para proveer al método Find de una filtro personalizado, es decir, definir nosotros cómo queremos filtrar los datos, vamos a ver el código interno del método Find

public T Find(Predicate match) {
	if( match == null) {
		ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
	}
	Contract.EndContractBlock();

	for(int i = 0 ; i < _size; i++) {
		if(match(_items[i])) {
			return _items[i];
		}
	}
	return default(T);
}

El predicate es la variable match y vemos que lo que hace este método Find es recorrer todos los elementos de la lista y si match es true, retorna el elemento que coincide. Esto nos demuestra la utilidad de los delegados, podemos nosotros definir el criterio de búsqueda.

Existen muchos otros métodos en la clase List<T> que aceptan un predicate y en otras clases también.

Action y Func

Action y Func son más simple, si miramos su definición nos damos cuenta para qué sirven

public delegate void Action();
public delegate void Action(T obj);
public delegate TResult Func();
public delegate TResult Func(T arg);

En el caso de Action es una delegado pre-definido que nos permite definir “acciones” es decir, métodos que no devuelven un valor, el ejemplo del principio lo podríamos haber hecho con Action.

public void DoSomething(Action delegado)
{
    delegado();
}

Lo mismo que si quisiéramos pasar uno o varios parámetros

public void DoSomething(Action delegado)
{
    delegado(20);
}

Existen muchas sobre cargas genéricas para poder pasar hasta 16 parámetros.

En el caso de Func es como un Action pero que devuelve un valor, entonces nuestro código final usando un Func quedaría así:

public void DoSomething(Func delegado)
{
    Console.WriteLine(delegado(20));
}

Simplemente Action y Func no son más que delegados pre-definidos que nos ahorran crear los nuestros en la mayor parte de los casos.

Es importante comprender bien los delegados porque están por todas partes, sobre todo en Linq, todo lo que sea asíncrono como HttpClient o lo relacionado con Threads.

Nos leemos.

Azure DevOps: ¿Cómo consumir un feed nuget de Azure DevOps en nuestra app local?

Dentro de la característica de artefactos de Azure DevOps podemos crear nuestros propios feeds de paquetes nuget para organizar nuestros componentes y reutilizarlos.

Acceder al feed

La pregunta es cómo hacer para desde nuestro entorno local Visual Studio o Visual Studio Code o mejor dicho el compilador de .NET pueda acceder al feed.

Para esto necesita como mínimo conocer la URL del feed, esto se obtiene fácilmente desde Azure DevOps, vamos al feed y presionando el botón “Connect to feed” vemos la URL.

 

image

Obtener credenciales de acceso al feed.

Con la URL mucho no vamos a poder hacer si no tenemos permisos de acceso, dentro de Azure DevOps esto se logra creando tokens de acceso a nivel usuario. Es por esto vamos directamente a la configuración de seguridad del usuario.

image

Y vamos a la parte de security tokens.

image

En la sección “Personal access token” seleccionamos “New Token”, definimos nombre y la duración y lo más importante, el scope.

El scope nos permite definir para qué puede ser usado el token y solo para eso, en este caso le daremos un único scope, que será Packaging.Read.

Por defecto este scope no se ve por defecto hasta que hagamos click sobre el link debajo que dice “Show all”.

Ventaja de los tokens:

  • Usar tokens en lugar de usar el password tiene varias ventajas, vamos a enumerarlas
  • Podemos usarlo en un entorno sin poner en riesgo el password.
  • Tienen un acceso limitado a los recursos, por ejemplo los feeds.
  • Tienen un vencimiento definido, con lo cual si lo perdemos lo borramos y listo.

Paso final, crear el Nuget.config

Con estos datos lo último que tenemos que hacer es ponerlos en un archivo que colocaremos a nivel de nuestra solución, el formato del archivo es el siguiente (es un xml):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="Azure" value="https://pkgs.dev.azure.com/leomicheloni/_packaging/MyNuget/nuget/v3/index.json" />    
  </packageSources>
  <packageSourceCredentials>
    <Azure>
      <add key="Username" value="mail@mail.com" />
      <add key="ClearTextPassword" value="prrryxncm6drvvruhmrph3rm5jiwrpp73viemx4n3kdo6dxwzlita" />
    </Azure>
  </packageSourceCredentials>  
</configuration>

Pueden descargar un ejemplo de un Nuget.config desde acá.

Y con esto tenemos acceso a nuestro feed, nos leemos.

Leonardo.

Los memes de Javascript

No pasan más de 10 minutos desde que algo ocurre en el mundo hasta que Internet se llena de memes al respecto; sin embargo últimamente se ven muchos memes sobre Javascript y la idea de este post es explicarlos, o mejor dicho, explicar por qué son incorrectos.

El meme en cuestión

En meme del que voy a hablar en esta ocasión es éste, con Patrick Star de protagonista:

 

image

 

En este caso es una burla acerca de ciertos casos con las comparaciones en Javascript, y si bien tiene algo de gracia demuestra más que nada desconocimiento del lenguaje y vamos a explicarlo.

El comparador de igualdad

El comparador de igualdad de Javascript tiene una característica interesante que se podría resumir como que “hace el mejor esfuerzo por comparar los dos términos” para explicarlo simple: el comparador convierte los dos término en caso de no ser del mismo tipo y luego hace una comparación estricta, entonces esto nos lleva a la primera parte del meme:

0 == “0”

Básicamente al usar el comparador de igualdad == Javascript detecta que los términos no son del mismo tipo y los convierte, entonces esta comparación pasa a ser verdad como podemos ver al probarlo en Nodejs

image

es por eso que si queremos una comparación estricta usamos el operador de comparación estricta ===

image

Entonces, primer caso resulto, Javascript hace exactamente lo que dice la documentación que debe hacer, una comparación con conversión de tipos.

Un array vacío

Los arrays siempre tienen sus bemoles en todos los lenguajes y Javascript no es la excepción, pero por qué  0 == [ ] ?

La respuesta es que la conversión de un array vacío a entero nos retorna el valor de una posición de memoria vacía que es comparable con 0, entonces la comparación es verdadera, una vez más si usamos el comparador estricto es no es así:

image

La comparación con un string es false

 

"0" == [] 

Acá es simple, basados en lo anterior, es evidente que podemos convertir un array vacío a entero y nos retorna algo comprable con false porque después de todo estamos pidiendo que haga un esfuerzo por convertir una posición sin valores. En este caso el término de la derecha resultará ser o o algo comparable con false, sin embargo ahora el término de la izquierda es un string que a lo sumo es comparable con un 0.

Conclusión

Un lenguaje de programación es complejo y tiene detalles, si en el día a día lo usamos debemos conocer sus características y no olvidarnos que puede ser (como en el caso de Javascript) un lenguaje diseñado hace muchos años y si estamos acostumbrados a lenguajes más modernos que han aprendido de los problemas que pueden acarrear estas cosas y que los programadores de hoy en día usan un lenguaje sin conocerlo…

 

Nos leemos.

#NetConf en la Universidad Politécnica de Madrid

El evento

Como parte de evento que se realiza en todo el mundo durante estos meses, he tenido la suerte de organizar y participar como ponente en la NetConf en Madrid.

Gracias a la generosidad de la gente de la Universidad Politécnica de Madrid el evento ha tenido una locación inmejorable.

Ha sido una versión de tres charla en la que he tenido la suerte de compartir cartel con dos grandes del mundo de .NET de España como Javier Valero y Robert Bermejo.

Sobre Azure DevOps

Cuando preparé la charla no existía Azure DevOps por lo tanto mi charla fuer sobre Visual Studio Team Services, en concreto sobre cómo montar un entorno de despliegue continuo de una aplicación ASP Net Core en Docker sobre Azure.

Dejo un link a las diapositivas que utilicé durante la charla.

Gracias a los ponentes, a la UPM y a Tokiota por el apoyo.

Nos leemos.