miércoles, 29 de abril de 2015

Preguntas de Entrevista .NET - Parametros por valor o referencia?

Si bien esta pregunta apunta a ver si tenemos los conocimientos mínimos sobre el lenguaje, es una de las que mas falla tiene a la hora de las preguntas y respuestas en una entrevista para el puesto de programador .NET. Y por que tantas fallas? bueno yo imagino que a la hora de aprender aprendieron lo que dice los libros textual y no fueron mas allá. La mayoría de las veces que vi a gente con muchos años de experiencia no saber cual seria el valor del output luego de llamar a un método.
Mi idea acá es con tres sencillos métodos aclarar un poco esta cuestión.

Quien es quien para el framework?

Vamos a aclarar cuales son las diferencias entre un parámetro que ingresa por valor y por referencia.  Según lo que podemos leer en miles de libros que andan dando vuelta o incluso en miles de blogs en la web un parámetro por valor es aquel que a un determinado método ingresa una copia del valor, en pocas palabras si nuestra variable contiene el valor 3 (utilice un int por un motivo especial) cuando llamamos a un método el framework genera una copia del valor de la variable y se lo pasa como parámetro al método. Esto es sin mas un parámetro que ingresa por valor, cual es la ventaja? la primera la velocidad, ya que estas variables se encuentran en el sector de memoria conocido como heap, con lo cual utilizan mucha menos memoria y el acceso es mas rápido. porque utilice un valor numérico para mi ejemplo? bueno básicamente porque los llamados tipos base mas los structs se alojan en el heap con lo cual siempre ingresan en un método por valor.

static void IncrementaValor(int a)
{
     a++;
     Console.WriteLine("El valor incrementado en el metodo: {0}", a);
}

En el ejemplo que vimos recién tenemos un método que recibe un número por parámetro, lo incrementa y lo muestra por pantalla. Cuando termina la ejecución por pantalla vemos al número que pasamos por valor incrementado. Ahora que pasa con nuestra variable fuera del método, la realidad es que como el framework paso una copia de nuestro valor nuestra variable quedo inmutable y conserva el valor previo a ingresar al método y eso lo podemos verificar con la siguiente prueba.

var num2 = 2;
Console.WriteLine("El valor de num2 antes de llamar al metodo: {0}", num2);
IncrementaValor(num2);
Console.WriteLine("El valor de num2 despues de llamar al metodo : {0}", num2);

Los parámetros por valor nunca se modifican?

Bueno esta es una pregunta capciosa, la realidad es que si podemos modificarlo haciendo una pequeña modificación a nuestro método.

static void IncrementaValor(ref int a)
{
     a++;
     Console.WriteLine("El valor incrementado en el metodo: {0}", a);
}

Como podemos ver ahora nuestro método tiene un modificador en el parámetro que es la palabra reservada ref la misma nos permite decirle al framework que nuestra variable queremos que entre al método por referencia, es decir en lugar de hacer una copia del valor queremos que una referencia a nuestra variable sea enviada así podemos modificar el valor interno de la misma. Esto lo podemos comprobar fácilmente con el siguiente código.

var num2 = 2;
Console.WriteLine("El valor de num2 antes de llamar al metodo: {0}", num2);
IncrementaValor(num2);
Console.WriteLine("El valor de num2 despues de llamar al metodo : {0}", num2);

Y qué parámetros son por referencia?

Bueno para concluir con esta pregunta los parámetros que ingresan a los métodos por referencia (sin necesidad de utilizar la palabra reservada ref) son los objetos en general. Siempre que pasamos como parámetro un objeto este ingresa al método por referencia. Dicho esto, cada vez que modifiquemos algo de un objeto en un método cuando termine el ámbito de ejecución del método nuestro cambio va a seguir ahi.

public class Numero
{
    public int Valor { get; set; }
}

static void IncrementaValor(Numero num)
{
     num.Valor++;
     Console.WriteLine("El valor incrementado en el metodo: {0}", num.Valor);
}

En la modificación que hice al método anterior podemos ver que enviamos un objeto y en la validación vemos que el cambio tiene efecto al salir del método.

var num2 = new Numero();
Console.WriteLine("El valor de num2 antes de llamar al metodo: {0}", num2.Valor);
IncrementaValor(num2);
Console.WriteLine("El valor de num2 despues de llamar al metodo : {0}", num2.Valor);

La idea de esta pregunta es ver si sabemos los conceptos básicos del framework, como funciona internamente y si principalmente hemos ido mas allá del concepto general de los libros o la web.

martes, 28 de abril de 2015

Preguntas de Entrevista .NET - Qué es Generics?

Bueno continuando con la serie de entradas dedicadas a analizar las preguntas que suelen aparecer en una entrevista para un puesto de desarrollador .NET. La pregunta que voy a intentar responder es la que aparece en casi todas las entrevistas en las que participe y es "Qué es Generics?". Lo primero que se nos viene a la cabeza a la hora de pensar en Generics es las colecciones. Y no esta mal que pensemos eso ya que siempre que se habla de Generics se lo asocia directamente a las listas genéricas que si, utilizan Generics pero no son el concepto de Generics en si mismas.

Entonces, qué es Generics?

Bueno la respuesta es verdaderamente muy sencilla. Generics es una herramienta que nos brinda el framework para separar el comportamiento del tipo de datos. Veamos un ejemplo sencillo que nos va a ayudar a ver mas claramente esto. Supongamos que tenemos la siguiente clase con un método estático que nos retorna cuando dos strings son iguales.

class check
{
    public static bool Compare(string a, string b)
    {
        return a.Equals(b);
    }

}

Como podemos ver es una clase muy sencilla pero si miramos en detalle vemos rápidamente que hay un problema. Este método solo nos sirve para comparar strings, con lo cual si quisiéramos comparar otro tipo de datos deberíamos sobre cargar el método Compare tantas veces como tipos de datos deseados. Y si bien esto funciona como podemos ver el código no queda limpio y el mantenimiento de esto es muy tedioso.

class check
{
    public static bool Compare(string a, string b)
    {
        return a.Equals(b);
    }
    public static bool Compare(int a, int b)
    {
        return a.Equals(b);
    }

    public static bool Compare(DateTime a, DateTime b)
    {
        return a.Equals(b);
    }
}

Entonces existe otra forma de hacer esto de una manera mas "genérica"? 

Si claro, podríamos definir nuestro tipo de dato como object. Y si esto es valido pero nos genera una sobrecarga de boxing y unboxing innecesaria. Para este tipo de cuestiones donde nosotros queremos separar el comportamiento del tipo de dato. Como hacemos estos? bueno lo primero que tenemos que hacer es definir el tipo de dato genérico que vamos a utilizar en nuestro método y eso lo hacemos utilizando los símbolos de < y > definiendo el tipo de dato adentro (generalmente se utiliza la letra T) pero cabe aclarar que podemos poner cualquier identificador ahi como podemos ver en el siguiente código.

class check
{
    public static bool Compare<UNKNOWTYPE>(UNKNOWTYPE a, UNKNOWTYPE b)
    {
        return a.Equals(b);
    }
}

Ahora que tenemos definido nuestro método de manera genérica vamos a ver como tendríamos que invocarlo.

Console.WriteLine("comparo numeros: " + check.Compare<int>(1,2));
Console.WriteLine("comparo strings: " + check.Compare<string>("hola", "hola"));

Como podemos ver ahora nuestro método sin necesidad de cambiarlo funciona con cualquier tipo de datos. Algo importante de aclarar es que el tipo de dato que utilicemos al momento de invocar nuestro método debe ser el mismo de los paramentros (porque así lo definimos). Si hubiéramos querido tipos de datos distintos lo deberíamos haber aclarado en la declaración de nuestro método. Les dejo la prueba con multiple tipos de datos genéricos a ustedes.
Entonces cuando nos encontremos con esta pregunta en una entrevista sin dudarlo debemos explicar que Generics nos brinda la posibilidad de separar nuestro comportamiento del tipo de dato, y esto lo podemos hacer a nivel de clase o de método.

Preguntas de Entrevista .NET - Diferencia entre var y dynamic

Voy a empezar a escribir una serie de entradas y esta es la primera sobre las preguntas frecuentes que nos podemos encontrar en una entrevista de trabajo cuando aplicamos para posiciones de desarrollador .NET. Estas entradas van a estar orientadas a explicar los conceptos que los entrevistadores suelen preguntar y que es lo que esperan como respuesta. Muchas veces nos parece que las preguntas no tienen sentido o creemos que son funcionalidad que no se suelen utilizar. Sin embargo es bueno saber que cuando el entrevistador hace la pregunta es porque esta esperando un conocimiento de nuestra parte. Sin mas preámbulos vamos a tema que voy a hablar en esta entrada.

Diferencias entre VAR y Dynamic


Para los que no están familiarizados con el tema los keywords VAR y Dynamic nos brindan la posibilidad de no definir el tipo de dato que vamos a utilizar al momento de declarar nuestras variables. De esta manera nuestra declaración de variables quedaría así:

var x = "string";
dynamic y = "string";

Si comparamos estas dos variables vamos a obtener como resultado que ambas son strings y que ambas contienen la palabra "string".

Ahora si ambas me dan como resultado el mismo tipo de objeto, para que existen dos palabras reservadas que hacen lo mismo? bueno la respuesta rápida a esta pregunta es que parece que hacen lo mismo pero no lo hacen.
Como es esto? bueno es sencillo, la principal diferencia entre ambas es cuando se acoplan al tipo de datos, y esto es uno de los puntos mas importantes que marca, a mi entender, la mayor ventaja de dynamic sobre var. 
Cuando declaramos una variable utilizando la palabra reservada var esta debe ser inicializada en ese mismo momento. por que? bueno la respuesta es por lo que estuvimos hablando antes, var se acopla al tipo de datos en tiempo de codificación con lo cual una vez que inicializamos la variable la misma queda asociada al tipo de datos con el que la estamos asociando. Por mas que de la impresión de que no estamos poniendo el tipo de datos si lo estamos haciendo y nuestro código sigue siendo fuertemente tipado, y no vamos a poder guardar en esta variable otra cosa que no sea lo que guardamos cuando la declaramos. 
Por otro lado, cuando declaramos una variable utilizando dynamic no es necesario que la inicialicemos para que funcione. porque esto? porque dynamic se acopla al tipo de datos en tiempo de ejecución utilizando reflection. Como podrán imaginar una de las mayores ventajas de dynamic es que convierte a nuestra variable en débilmente tipada. Esto quiere decir que el código que pongo a continuación es perfectamente valido.

dynamic y = "string";
Console.WriteLine("Contiene: {0}", y);
y = 1;
Console.WriteLine("Contiene: {0}", y);

Una de las mayores ventajas que nos da dynamic es la flexibilidad como pudimos ver recién, sin embargo una de las desventajas es la que tienen la mayoría de los lenguajes débilmente tipados y es que podemos cometer un error al llamar alguna método o bien no saber que esta almacenado en la variable. Al utilizar reflection no nos damos cuenta del error hasta que la aplicación esta ejecutando.
La ventaja que nos dar la utilización de var es que muchas veces la inicialización de una variable es una sentencia larga que suele ser tedioso y poco vistoso repetir o simplemente no sabemos cual es el tipo de datos ya que la inicialización es el resultado de una ejecución de LINQ. En esos casos la utilización de var es una manera rápida y declarar variables.

Para concluir, lo que busca un entrevistador con esta pregunta es ver cuanto conocemos del framework y cuanto utilizamos del mismo o si solo respondemos porque lo vimos así en algún lado y hacemos las cosas de manera automática.