Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 9 de mayo de 2017
C#Seguimos revisando las novedades que nos llegan de la mano de C# 7, la nueva versión del lenguaje aparecida junto a Visual Studio 2017.

En un post anterior ya profundizamos un poco en las funciones locales, y hoy veremos en qué consisten las nuevas inline out variables, una característica muy útil que nos ahorrará escribir código en escenarios en los que siempre hemos tenido la sensación de que C# podía hacer algo más por nosotros.

Esa extraña sensación…

Observad el siguiente código; seguro que habéis escrito algo parecido más de una vez (y dos, y tres… centenares ;D)
public void ShowInteger(string str)
{
   int number;
   if (int.TryParse(str, out number))
   {
       Console.WriteLine("Number: " + number);
   }
}
En mi caso, cuando escribo un código de este tipo, es raro que antes de comenzar a escribir la línea del TryParse() haya previsto que necesitaré una variable int. Normalmente escribo las llamadas a métodos con parámetros out, y mientras voy haciéndolo me doy cuenta de que las necesito, por lo que tengo que tengo que volver atrás, insertar la línea para declarar de forma estrictamente tipada la variable de salida, y después continuar por donde estaba. No es que rompa la productividad de la jornada, pero realmente resulta algo molesto.

imageTambién he de decir que esta molestia se relajaba un poco con las versiones modernas de Visual Studio, pues las quick actions (Ctrl+.) ya nos ofrecen soluciones automáticas al problema. Lo mismo ocurre con Resharper, que puede detectar este caso y solucionarlo a golpe de Alt-Enter.

Otro inconveniente asociado a esta forma de definir los parámetros de salida es que muchas veces debíamos definir las variables en un ámbito superior a aquél en el que íbamos a utilizarlas. Por ejemplo, en el bloque de código que hemos visto antes, era habitual es que el entero number lo usáramos exclusivamente en el interior del bloque if, por lo que su declaración fuera de éste tampoco tenía mucho sentido.

Por todos estos motivos, la sensación de que C# se quedaba algo corto en este escenario siempre ha estado ahí, y esto es lo que viene a solucionarse en la versión 7.

Inline out variables

A partir de ahora podemos utilizar esta nueva sintaxis, más concisa y fácil de leer, usando inline out variables:
public void ShowInteger(string str)
{
   if (int.TryParse(str, out int number))
   {
       Console.WriteLine("Number: " + number);
   }
}
El resultado de este código es exactamente el mismo que vimos al principio. Internamente se crea una variable de tipo entero llamada number en el ámbito del método ShowInteger(), que puede ser utilizada en cualquier punto del método una vez ha sido declarada:
Console.WriteLine("Number: " + number); // No compila: se usa "number" antes
                                        // de ser declarado

if (int.TryParse(str, out int number)) {
    Console.WriteLine("Number: " + number); // Ok
}
Console.WriteLine("Number: " + number); // Ok, aunque "number" puede no haber
                                        // sido inicializado
Otro aspecto interesante, y que resulta bastante cómodo de utilizar, es que gracias a la inferencia de tipos podemos utilizar var para su declaración, pues ya el compilador es capaz de determinar de qué tipo se trata:
public void ShowInteger(string str)
{
   if (int.TryParse(str, out var number))
   {
       Console.WriteLine("Number: " + number);
   }
}
Por último, hay veces en las que invocamos un método con parámetros de salida cuyos valores no vamos a utilizar posteriormente. Para no obligarnos a declarar más variables de la cuenta, podemos utilizar el comodín "_" (guión bajo) para indicar al compilador que puede ignorar dichos valores:
public static void GetSomething(out int x, out double y, out string z)
{
    x = 100;
    y = 100.0;
    z = "hello";
}

// Uso del método:
GetSomething(out var x, out _, out _);
Console.WriteLine(x); // Shows "100"
Visual Studio 2015 usando inline out vars¿Interesante, verdad? Pues recordad que, además de en Visual Studio 2017, también podéis usarlo en Visual Studio 2015 si instaláis o actualizáis a la última versión el paquete nuget "Microsoft.Net.Compilers"; aunque en el IDE se muestren como errores, la compilación irá bien y todo funcionará correctamente.

Publicado en Variable not found.

6 Comentarios:

Rfog dijo...

Mira que me gusta poco esas cosas del "syntax sugar", pero joder, a veces hay que aplaudir.

Aunque en este caso oculta un poco la declaración de la variable, te ahorra un tiempo precioso. Además, con los resaltadores de sintaxis e IDE modernos, siempre podemos "ir a declaración" (o como se llame).

Mira que en su momento protesté con la declaración automática (var en C#, auto en C++), y ahora lo uso siempre que puedo... aunque en C++, con los lambda y otras zarandajas, si no usas auto eres candidato de psiquiátrico. Incluso a veces declaro algo como auto, o hago una llamada con una variable compleja y declarada como auto, y luego dejo al intellisense (el del propio vs o el de ReSharper, no sé cuál de los dos lo hace) que me cree la firma del método. Así a veces hasta me entero yo mismo del tipo.

(Joer, el rfog hablando mal de C++. Voy a pedir cita al loquero :-P)

José María Aguilar dijo...

Pues sí, quién te ha visto y quién te ve ;DDDD

También miré los "var" de C# con recelo, y ahora es rara la vez que no los uso. Seguro que podemos convivir con esa ligera ocultación de la variable a cambio de un poco más de velocidad al escribir ;)

Gracias por comentar & un saludo!

Julen dijo...

Igual es que estoy ciego... pero no veo el ámbito DoSomething() por ningún sitio... (Y sí, he hecho Ctrl+F en el navegador para buscarlo).

José María Aguilar dijo...

Hola!

El problema de escribir código en un blog es que no se compila y es fácil que se cuelen gazapos como este ;DD

Muchas gracias por informar, el post ya está actualizado.

Saludos!

LuisLAP dijo...

"Mira que me gusta poco esas cosas del "syntax sugar""

Sin azúcar sintáctico (cualquiera, incluso el "var"), el código que escribiríamos sería muchísimo (bastante) mayor.

Nunca he entendido a la gente que, en cada nueva revisión del lenguaje, se queja con las mejoras que se introducen, y a veces ni siquiera intentan entenderlas. Puede que algunas puedan parecer innecesarias para algunos, pero ninguna es obligatoria. Se puede seguir escribiendo código como con la primera versión de c#.

"También miré los "var" de C# con recelo, y ahora es rara la vez que no los uso. Seguro que podemos convivir con esa ligera ocultación de la variable a cambio de un poco más de velocidad al escribir ;)"

El caso de var es incluso extraño, mucha gente aun se queja del uso de var, cuando en f# la norma es declarar así:

let identificador = valor

Que es básicamente lo mismo que (con las diferencias de la inmutabilidad):

var identificador = valor;

De hecho me parece tan arcaico hacer cosas como:

string[] arreglo = new string[] {"Uno", "Dos"};

Cuando esto no solo es mas corto, sino igual o mas claro:

var arreglo = new[] {"Uno", "Dos"};

La inferencia de tipos es muchisimo mas agresiva en f# (o lenguajes como Haskell) y es una gozada no tener que escribir tanto tipo. Debe ser cosa de costumbre que la gente se queje del uso de var, porque de otra forma no entendería las quejas.

Cuál función de suma es mas clara y corta ¿la de f#?

let suma x y =
x + y

o la de c#:

Func suma = (x, y) =>
x + y;

Rfog dijo...

LuisLAP, mira que te gusta retorcer mis comentarios para lucimiento propio. ¿Cómo es que la parte "tengo que aplaudir" no la citas? ¿Y cómo es que reinterpretas que no me gusta la declaración de variables automáticas?