Runing Tests and Code Coverage without Visual Studio. OpenCover con coverlet y ReportGenerator.

imageMuy buenas,

Llevo ya un tiempo con ganas de escribir sobre este tema y, principalmente por el impacto que causa en DevOps, en donde últimamente estoy un poco más inmerso de lo habitual.

En primer lugar, me gustaría hacer mención a este post del compañero @snavarropino, donde nos habla de la Cobertura de Código y Azure DevOps (anteriormente conocido como VSTS).

Y, en segundo lugar quiero hacer mención también a esta reseña de Wikipedia:

La cobertura de código es una medida (porcentual) en las pruebas de software que mide el grado en que el código fuente de un programa ha sido comprobado. Sirve para determinar la calidad del test que se lleve a cabo y para determinar las partes críticas del código que no han sido comprobadas y las partes que ya lo fueron.

Cuando desarrollamos con Visual Studio, y ejecutamos tests, en la mayoría de las ocasiones hacemos uso del tooling integrado en Visual Studio, si bien, tenemos que reconocer que para poder lanzar la cobertura de código entre otras acciones que brinda, necesitamos disponer de la edición Enterprise, lo que supone un coste adicional, que en muchas ocasiones es tal que da lugar a evaluar y analizar el mismo frente al beneficio que aporta.

A continuación veremos como ejecutar los Tests y la Cobertura de código desde Visual Studio, tal y como estamos acostumbrados y también, desde la línea de comandos, con .Net Core.

Desde Visual Studio (Enterprise Edition)

Lanzamos la cobertura de código bien desde la opción de menú “Test – Analyze Code Coverage” o bien, desde el Test Explorer, “Analyze Code Coverage for Selected Tests”:

image

El resultado es el siguiente:

image

Donde, por ejemplo, para la clase ProjectService.cs, podemos ver que parte del código está cubierto (en azul) por los tests y que partes no.

image

Teniendo en cuenta esto, podemos ir afinando nuestros tests para cubrir más y más código. Existen indicadores referentes a este dato que sirven de orientación para medir la calidad de nuestros desarrollos, si bien, no olvidemos que la cobertura determina la calidad del test, (no la del código). Eso si, podremos conocer el porcentaje de código que es cubierto y en consecuencia asegurar que tal %, al menos está “testeado”, lo que supone una garantía de calidad.

Conseguir un 100% de cobertura, evidentemente supone un esfuerzo y un coste, y es aquí donde debemos poner especial atención. Tenemos que valorar el porcentaje a cubrir en base a este coste y tiempo. Un valor de este porcentaje orientativo puede estar entre el 60% y el 70%, pero va a depender de cada caso en particular.  Dejo aquí una referencia de Wikipedia, a: El Triangulo de Hierro (o Iron Triangle), para profundizar en este tema, al que quizás, otro día le dedique un post.

Desde Línea de Comandos (Sin Visual Studio)

Antes de continuar, es importante recordar que los tests han de ser excluidos de la cobertura indicándolo mediante el atributo [ExcludeFromCodeCoverage] a nivel de clase en los tests.  De igual forma, podemos también excluirlos haciendo uso del fichero “.runsettings”. Visitar este enlace, para más detalle.

Adicionalmente, añadir el paquete Nuget: “coverlet.msbuild”.

image

A continuación, en el siguiente fragmento de código, (“coverage.cmd”) contamos con todas las instrucciones para ejecutar los tests y visualizar la cobertura de código de forma similar a como lo hace Visual Studio.

Las líneas [19-24, se corresponden con el comando “dotnet test” que ejecuta los tests unitarios. Habilitan la cobertura de código, especifican el formato en el que generar la cobertura (“Open Cover”) y la ruta en la que se generará el fichero “.xml” con el resultado de la cobertura.

Si ejecutamos este comando, obtendremos la siguiente salida en relación a la cobertura de código:

image

Donde, podemos ver la cobertura para cada módulo y diferenciada por:

  • Línea. Número de líneas de código que son cubiertas.
  • Branch. Número de caminos diferentes que toma el código (para instrucciones, if, switch, etc.), que son cubiertos.
  • Método. Número de métodos que son invocados desde los tests.

Adicionalmente, podríamos utilizar el parámetro /p:Exclude=\”[].Models.*\”, para excluir del análisis, cualquier clase cuyo namespace coincida con el filtro indicado. Mas detalle aquí: coverlet.msbuild.

La línea 27. Instala la herramienta Report Generator, que va a permitirnos generar un informe similar al utilizado por Visual Studio.

La línea 28.  Ejecuta la herramienta, tomando como entrada uno o más ficheros (en formato .xml) generado tras la ejecución de los tests, indicado por el parámetro “p:/CoverletOutput” y como salida, –targetdir, la ruta en la que se generan los ficheros de informes en el formato especificado por el parámetro –reporttypes (Html y HtmlSummary).

Finalmente, la línea 30, lanza el navegador y muestra el fichero “index.htm” tal y como podemos ver en la siguiente imagen, con el resumen y el detalle de la cobertura.

image

¡Ahora ya no hay argumentos para no “cubrir” bien el código!

En siguientes posts, veremos como aplica todo esto a la Integración Continua dentro del mundo de DevOps, tanto en Jenkins, como en Travis, como en Azure DevOps.

Happy testing and good Coverage
Juanlu

Logging/Traces in NetCore projects with Serilog

imageBuenas,

Como en cualquier desarrollo, un buen sistema de Logging o Trazas para diagnósticos y detección de problemas, es una buena práctica que va a salvarnos de un aprieto más de una vez. En La mayoría de los casos, creamos un ApplicationBlock, un Helper, o similar para trabajar con un sistema de estas características, cuyo objetivo es escribir trazas en un repositorio: Consola, fichero y/o base de datos entre otros, con la intención de poder consultarlo a posteriori, ante cualquier problema, que como sabemos, siempre recurrimos a el en entornos Productivos.

Con NetCore, podemos hacer lo mismo como no podía ser de otra manera, si bien, una peculiaridad y gran ventaja, es la posibilidad de usar el Interfaz ILogger (Microsoft.Extensions.Logging), tanto en nuestro controladores como en nuestros servicios o cualquier clase, mediante Injección de dependencias, lo que nos permitirá codificar sin pensar el framework o factoría encargada de escribir trazas en un repositorio: consola, fichero, base de datos, etc.

Existen muchos frameworks, que nos permiten llevar a cabo esta tarea de manera muy facil: Serilog, NLog y Log4Net, entre otros. ¡Atrás quedo Enterprise Libray  ! Cada uno tiene sus particularidades, si bien, Serilog, es considerado como uno de los mejores, además, cuenta con un elevado número de extensiones para el guardo de trazas en diferentes repositorios: consola, fichero, RollingFile, base de datos, Azure ApplicationInsight, Azure App Service, etc., lo que lo hacen aun más potente.

Por tanto, veamos como trabajar con Serilog:

Por ejemplo, podríamos tener el siguiente código en nuestro Controller:

Donde “_logger”, dejará dos trazas en nuestro/s repositorio/s.  Podríamos codificar de esta misma forma todas aquellas de nuestras clases: Servicios, Repositories, etc., sin preocupación adicional, por el momento.

A continuación, en el fichero Program.cs, incluiremos la siguiente configuración:

Como buena práctica, dejaremos en manos del fichero “appSettings.json”, la configuración de el/los repositorio/s.

Otra ventaja de Serilog, como puede verse en el código anterior, es la capacidad de ejecución en modo “asíncrono”. Es decir, la escritura de trazas en un hilo adicional para no afectar a la ejecución normal del programa.

ver-github

Y ahora, veamos todo esto en ejecución:

Referencias:

Un saludo & Happy Logging
Juanlu

 

[Material] Evento Blazor (C# en el Browser)

image

Buenas,

Ayer 28 de Junio he vuelto a poder compartir conocimiento y muy buenos momentos con los compañeros de SVQDotNet, hablando de #Blazor en el evento: BLAZOR: Browser + Razor (C# en el Navegador) ¿Adios a JavaScript?

Dejo aquí el material empleado en la misma:

ver-github

En esta otra entrada puedes continuar profundizando.

Un saludo
Juanlu

Blazor 0.3.0/0.4.0-preview1-10286 ready!

image

El pasado 2 de mayo Blazor aparecía con su versión 0.3.0, y hoy, ya tenemos la versión 0.4.0-preview1-10286 lista para ser probada. Como ya sabemos, (según post anterior) al tratarse de un proyecto experimental requiere cambios constantes en nuestros proyectos (aun no recomendados para entornos de Producción).

Estos cambios, por tanto, nos obligan a realizar modificaciones en nuestra aplicación Taskin, que ya vimos en el post anterior (“¿Javascript ha muerto? .NET Web Assembly con Blazor”).

Según la release 0.3.0 e incluso para la 0.4.0-preview1, estas son las novedades:

    1. Project templates updated to use Bootstrap 4
    2. Async event handlers
    3. New component lifecycle events: OnAfterRender / OnAfterRenderAsync
    4. Component and element refs
    5. Better encapsulation of component parameters
    6. Simplified layouts

Y para hacer el Upgrade de 0.2.0 a 0.3.0:

  1. Instalar .NET Core 2.1 SDK (2.1.300-preview2-008533 o superior).
  2. instalar Visual Studio 2017 (15.7 Preview 5 or superior) con ASP.NET and web development workload selected.
  3. Instalar la última versión de la extensión “Blazor Language Services” del Marketplace de Visual Studio
  4. Actualizar el paquete Blazor y la Tool CLI a 0.3.0.
  5. Eliminar cualquier referencia al paquete: “Microsoft.AspNetCore.Razor.Design” asi como cualquier dependendencia.
  6. Actaulizar los proyectos a C# 7.3.
  7. Actualizar los parámetros usado en os componentes para que incluyan el atributo [Parameter].
  8. Actualizar los layouts para que hereden de “BlazorLayoutComponent” y eliminar la implementación de ILayoutComponent incluso la propiedad Body.

Tras la actualización, a continuación podemos una muestra de ello:

image

Y aquí, el código en Github: https://github.com/juanluelguerre/Taskin

Un saludo and happy Blazor coding
Juanlu

[Material] “.Net LOVE Open Source”

imageDurante el día de hoy ha tenido lugar l “I Jornada de conocimiento abierto“, en Huelva.

Ha sido un día interesante en lo que respecta al Software y Hardware libre así como en lo referente al Open Source, donde he tenido la oportunidad de participar, y, como no podía ser de otra manera con esta presentación “.Net LOVE Open Source“, en la que he tratado los siguientes puntos:

  • Free Software VS Open Source
  • Microsoft y el Open Source
  • .NET Open source
  • .NET Core
  • Azure, Dockery más…

A continuación dejo la presentación.

 

Un saludo & happy Open weekend

Juanlu

OpenAPI en mi API REST .NET Core con “Swashbuckle”

imageOpenAPI es un estándar para crear, administrar y consumir API REST. Conocido previamente como Swagger, en el último año ha sido adoptado por la Linux Foundation y obtuvo el apoyo de compañías como Google, Microsoft, IBM, Paypal, etc. para convertirse en un estándar para las API REST.

Cuando creamos un API Rest, tenemos varias opciones durante el desarrollo para comprobar que ésta funciona.  Quizás la más ocurrente es utilizar directamente el navegador e ir cambiando la url de cada uno de nuestros servicios u operaciones.  El principal problema con esto es que en un equipo de trabajo, no nos acordaremos de las urls, por lo que se comparten o anotan en alguna wiki o se contemplan otras opciones muy similares.

Dentro de estas otras opciones nos encontramos con: Fiddler, Avadced REST Client (extensión de Chrome), o Postman entre otras herramientas, que nos facilitan esta labor en alguna u otra medida. Por supuesto, y al margen de los Test Integrados, que veremos en algún otro post (con xUnit), Postman es realmente la que mas me gusta y, en mi opinión, la más útil de todas. Además de hacer estas pruebas de las que comentamos, nos permite: diseñar APIs, crear Mocks, test automáticos, documentarlas y mucho más.

image

De igual forma, Open API, como estándar es la opción que estamos buscando, tanto para el “testeo” del que hablamos, como para ayudarnos con la documentación, para la exploración de APIs, e incluso para la auto-generación de SDKs.

Tanto Postman como OpenAPI, son herramientas complementarias, si bien, al crear nuestras propias API, el hecho de utilizar OpenAPI nos va a proporcionar:

  • Definición y documentación
  • Cumplimiento del standard
  • Auto-generar SDKs para que terceros puedan comunicarse
  • Personalización
  • Visualización
  • Ejecución y pruebas
  • Gratis para su uso
  • Y además, muy fácil de implementar en .NET

Al hablar de diseño de API y refiriéndonos a OpenAPI, implícitamente estamos hablando de JSON o YAML, dos formatos de ficheros también estándares, que van a permitirnos definir y diseñar las mimas. La versión actual de la especificación es la 3.0.1 y orientada a YAML y la versión previa la 2.0, que es idéntica a la especificación 2.0 de Swagger antes de ser renombrada a “Open API Specification”.

En el momento de escribir el post, el tooling para trabajar con la versión 3.0, aún es limitado.

Diseñando un API

Veamos como diseñar un API :

image

  • Una vez concluido el diseño, estamos en el momento de auto-generar, para diferentes lenguajes, el servidor: haskell, rails5, rust-server, spring, asp.net core, etc., y el cliente: eiffel, java, html, groovy, go, jmeter, scala, javascript, typescript-jquery, angular, C#,  etc.

image

  • Con el código resultante tras la auto-generación, tendríamos prácticamente, desde el día 1 de desarrollo, un API desplegada a modo de Mock. Importante, principalmente para desarrolladores Front, que necesitan un API, que probablemente no será desarrollada hasta una fase posterior. ¡IMPORTANTE Evitemos bloqueos entre equipos y tareas. Diseñemos APIs!

Nota: En esta URL: https://app.swaggerhub.com/apis/juanluelguerre/Taskin/v1, he publicado la versión 1.0 (muy sencilla) de Taskin, sobre la que podremos probar.

Creando APIs con NET Core y OpenAPI

Otra de las opciones, también importante es que si comenzamos un desarrollo desde cero, en base a una arquitectura propia y dependiente de cada proyecto, necesitaremos que el código auto-generado, se adecúe a la misma.  Para ello, tendremos dos alternativas:

  1. Trabajar con el SDK de OpenAPI y modificar las plantillas de auto-generación.
  2. Integrar OpenApi directamente en nuestro código .NET.

De acuerdo al objetivo de este Post, optaremos por la alternativa 2, donde para ellos seguiremos los siguientes pasos:

  • Crear un proyecto “ASP.NET Core Web Application”
  • Seleccionar el tipo de aplicación: API. Por el momento, no marcaremos la opción de Docker.
  • Para .NET Core 2.1, por defecto usamos HTTS, por lo que incluimos una nueva variable de entorno ASPNETCORE_HTTPS_PORT con el valor del puerto HTTS (ej: 5003) o bien la instrucción services.AddHttpsRedirection(options => options.HttpsPort = 5003);
  • Añadir la referencia al paquete NuGet: Swashbuckle.AspNetCore
  • Añadir el siguiente código al final del método “ConfigureServices(IServiceCollection services)” del fichero Startup.cs
  • Añadir el siguiente código al final del método “Configure(IApplicationBuilder app, IHostingEnvironment env)” del fichero Startup.cs.

image

  • En este punto podremos probar nuestra aplicación, sin necesidad de recordar la url de cada operación. Comprobaremos que de un simple string “[“value1”, “value2”]”  como resultado, pasamos a visualizar, navegar, ejecutar y depurar fácilmente.

image

Nota: Si navegamos al json “/swagger/v1/swagger.json”, es decir, a la url: https://localhost:5003/swagger/v1/swagger.json, obtenemos el “.JSON” correspondiente a la especificación OpenAPI, y,  al utilizarlo en el editor Online de Swagger, como vimos al principio del post, verificaremos, que nuestra API REST es correcta y por tanto cumple con el estándar.

image

Otra alternativa para la generación de Servidor y/o Cliente es “NSwag Studio”, que ya comentamos brevemente en un post anterior, se trata de una aplicación de escritorio, con ciertas opciones de personalización. Así mismo, también podemos utilizarla al igual que “Swashbuckle”, para integrarla en nuestra API REST .NET Core.

Y, para finalizar, si estas pensando en migrar tu especificación OpenAPI 2.0 a la versión 3.0, puedes utilizar esta herramienta: https://openapi-converter.herokuapp.com/

Espero que haya sido de utilidad

Saludos & Happy Coding!
Juanlu

¿Javascript ha muerto? .NET Web Assembly con Blazor

imageDurante el pasado fin de semana, entre algo de running, y alguna que otra fiesta, al fin he decidido aventurarme con Blazor.   Es cierto, que tengo pendiente otros “TO DOs”, como por ejemplo  profundizar en Angular y otros frameworks Javascript. Pero,… ¿Realmente lo necesitaré? ¡me pregunto!.

Como apasionado del mundo .NET, ¿Porque cambiar de lenguaje de programación para desarrollar Front? ¿Porque no desarrollar siempre con .NET?

Veamos a continuación si realmente Javascript ha muerto o estamos ante una nueva era/moda o simplemente una alternativa más ¿Quizás ha llegado ya el momento de que Web Assembly esté maduro?¿DLLs que se ejecutan en el navegador? 

¿Quieres saber más de todo esto? Continua leyendo, vayamos poco a poco conociendo estos nuevos conceptos.

¿Que es Web Assembly (abreviado Wasm)?

WebAssembly (Wasm) es un formato de código binario portable (bytecode), para la ejecución íntegra en navegador de scripts de lado del cliente. Se trata de un lenguaje de bajo nivel, diseñado inicialmente como formato destino en la compilación desde C y C++ entre otros.

El resultado de usar Wasm en lugar de Javascript, es una aplicación mucho más rápida, tanto durante la carga como en ejecución. ¿Quieres saber porqué? Echa un ojo a este enlace.

¿Que es Blazor?

Ahora que sabemos lo que es Wasm, podemos decir que Blazor es la implementación de Microsoft .NET para generar ensamblados Wasm.  Y, mas concretamente, un framework para la construcción de páginas web (SPA) basadas en .NET (C# y Razor Pages) y HTML  que se ejecuta en el navegador a través de WebAssembly. Habilita el desarrollo web full stack con la estabilidad, consistencia y productividad de .NET.

¿Aún te quedas con ganas de conocer más? Echa un ojo a este otro link. ¡Y, Recuerda que “Razor” y “Razor Pages”  son cosas diferentes!

Ahora si, es el momento de ponerse con el código, y lo haremos partiendo de este Get Started, que resumo brevemente:

Requisitos/Herramientas

1.- Instalar NET Core 2.1 Preview 1 SDK.

2.- Instalar la última Preview de Visual Studio 2017 (15.7). ¡Tranquil@, puede convivir con tu Visual Studio sin ningún problema!

3.- Instalar ASP.NET Core Blazor Language Services extension o bien, directamente desde Visual Studio, configurar una nueva fuente “https://dotnet.myget.org/F/blazor-dev/vsix/” e instalar. Esta última alternativa nos permitirá disponer de las notificaciones de actualización en todo momento, dado que aun no se encuentra la extensión de Blazor en el Market Place.

image image

Un Nuevo Proyecto

1.- Crear un nuevo proyecto de tipo ASPNET Core Web Application:

image

2.- Seleccionar uno de los dos tipos de proyecto para Blazor: Blazor o Blazor (ASP.NET Core hosted).

 image

3.-  Actualizar referencias NuGet. Incluir una nueva fuente nos permitirá de las actualizaciones mucho más rápidamente.

image

4.- Compilar y ejecutar la solución. Si has optado por crear el proyecto de tipo Blazor (ASP.NET Core hosted), establece como “Startup Project” el proyecto con el sufijo “Server” , de los tres generados.

blazor-home

Nota: Por cada carpeta  Shared y Pages se generan namespaces, por lo que es recomenable que los nombres de los proyectos y  ensamblados coincidan con los namespaces. ¡Esto cosa de “Razor Pages”, que a diferencia de MVC, está basado en páginas en lugar de Controllers!

Además de los ejemplos del “Get Started” anterior, aquí dejo el código (Github) de mi proyecto Taskin, con el que podrás cacharrear cuanto quieras y seguir profundizando.

image

Un ejemplo, de donde es mejor usar Wasm, podemos verlo en este juego de demo o incluso, en algo más real, aquí.

Aspectos principales

  1. Layout. Cada fichero .cshtml con una instrucción “@implements ILayoutComponent” como primera línea, constituye un Layout. El Layout que usa cada aplicación se indica en el fichero _ViewImports.cshtml como: “@layout NOMBRE_LAYOUT
  2. Componentes. Cada página .cshtml es un componente Blazor. Para usar un componente, únicamente tenemos que escribirlo como si de un tag HTML se tratará. Ej.: “<Counter />”. Además,  éste puede tener parámetros (propiedades públicas) permitiendo así ser usados desde cualquier página u otro componente.
  3. App.cshtml. Utiliza el Router para realizar el enrutado de las peticiones (o requests) a componentes Blazor específicos. “<Router AppAssembly=typeof(Program).Assembly />”.
  4. Routing. La directiva @page, indica a cada componente que éste, es una página. Sin esta directiva, ningún componente podría ser enrutado pero si ser usado por cualquier otro componente o página, que hiciera este enrutamiento.
  5. Dependency Injection. La inyección se lleva a cabo usando “@inject”   Ej.:“@inject HttpClient Http”
  6. Componente principal (o Root).  El componente principal de la aplicación se especifica en el EntryPoint:  Program.Main, definido en Program.cs, que es donde se configuran los proveedores de servicios (o services providers) para la aplicacion.
  7. Index.html.  Html que determina donde se reenderizará el comonponente. En tiempo de compilación la etiqueta “<script type=”blazor-boot”></script>” es reemplazada por esta otra “<script src=”_framework/blazor.js” reload=”/_reload” linker enabled=”true” references=”ElGuerre.Taskin.Models.dll,Microsoft.AspNetCore.Blazor.Browser.dll,Microsoft.Extensions.DependencyInjection.dll, …” entrypoint=”ElGuerre.Taskin.Blazor.Program::Main” main=”ElGuerre.Taskin.Blazor.dll”></script>”, que maneja el inicio de la aplicación y el punto de entrada a la misma.
  8. Hosting with ASP.NET Core. Para la publicación en ASP,NET Core, el proyecto “Server” hace referencia al proyecto cliente haciendo uso de un middleware que permite que Blazor pueda estar disponible en los navegadores: “app.UseBlazor<Client.Program>();”

Y, tranquil@, Javascript no ha muerto. Aquí puedes ver una prueba de ello, Wasm también puede ser usado desde Angular gracias a Emscripten. Podemos ver una colección de ejemplos sobre su uso en este enlace: https://boyan.io/angular-wasm/.

Esto sólo ha sido el principio, Wasm está comenzando y Blazor también, ¡eso si, hay que seguir disfrutando de todo lo que trae y seguirá trayendo Blazor!

Referencias:

¡A new era/seasson coud be comming!
Saludos & do Wasm !
Juanlu

Nuevas Características C# 7.1

cs71_featuresBuenas,

Siguiendo con las características de C#, en este post continuaremos con nuestro Tour y veremos concretamente las de C# 7.1:

  • Async Main Method
  • Default Literal Expressions
  • Inferred Tuple Element Names

ver-github

¡Recordemos que aquí tenemos los links a todos los post sobre las características de C# desde su versión 6.0: https://elguerre.com/2017/12/14/y-ms-new-features-c-7-0-2-2/!

Enjoy your coding !
Juanlu

Referencia: https://docs.microsoft.com/es-es/dotnet/csharp/whats-new/csharp-7-1

Y más… New features C# 7.0 (2/2)

imageHola,

Una vez más, continuamos conociendo más características de C# 7.0. En esta ocasión, las cinco restantes a las que ya vimos en el post anterior. Las conoceremos a través del siguiente vídeo:

Ver vídeo Youtube

Local Functions
More expression-bodied members
throw Expresions
Generalized async return types
Numeric literal syntax improve-ments

Y como viene siendo habitual, aquí tenemos el código para “cacharrear” todo cuanto queramos sobre estas nuevas características.

Resultado de imagen de github logos resources

Referencias:
Características de C# 6.0 Parte 1
Características de C# 6.0 Parte 2
Características de C# 7.0 Parte 1
– https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7

Saludos & happy coding in C#
Juanlu

Continuamos: New features C# 7.0 !

FeaturesCShar7-Parte1

Hola,

Continuamos conociendo características nuevas de C#, concretamente,  las de 7.0 y en profundidad, las cinco primeras de ellas en esta ocasión.

Como en post anteriores las veremos a través de un Video Tip (Video tutorial) que podemos encontrar en mi canal de Youtube: https://www.youtube.com/user/JuanluElguerre .

Imagen relacionada

En este pequeño vídeo mostraremos las siguientes características:

Out Variables
Tuples
Discards
Pattern Matching
ref Locals and Return

Resultado de imagen de github logos resourcesResultado de imagen de github logos resources


Referencias:
– Características de C# 6.0 Parte 1
– Características de C# 6.0 Parte 2
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7

Un saludo and happy improving your coding with C#
Juanlu