Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Expresiones new con el tipo de destino en C# 9
José María Aguilar - ¿Esa enumeración está vacía?
José María Aguilar
.NET Core / .NET
- El inyector de dependencias de .Net
Fernando Escolar - Consideraciones al publicar un paquete NuGet
Iván Montilla - Missing Stack trace when eliding the await keyword
Steven Giesel - Using the new configuration binder source generator: Exploring the .NET 8 preview
Andrew Lock - Log4net Appenders Introduction With C# Examples
Muhammed Saleem - How to Use Factory Pattern With Dependency Injection in .NET
Ahsan Ullah - 7 Things about C#: Console I/O
Joe Mayo - Microsoft .NET Code Analysis: Always Add Braces in C#
David McCarter - Test Data Generation With AutoFixture in .NET
Code Maze - Rx.NET v6.0: Enhancing Compatibility, Trimming Support, and Many More
Almir Vuk - LINQ: Select.Where or Where.Select?
Steven Giesel - Using Explicit Operators in Microsoft .NET to Perform Type Conversions
David McCarter - How to Hash Passwords with BCrypt in C#
Claudio Bernasconi - Introduction to .NET Releases And Updates
Aram Tchekrekjian - How to Generate C# Business Object Class from a CSV File
Greg Lutz
Publicado por José M. Aguilar a las 8:01 a. m.
Etiquetas: enlaces
Cuando en ASP.NET Core MVC usamos rutado por convención, lo habitual es que accedamos a las acciones mediante rutas definidas en el patrón, como [controller]/[action]
. Así, podemos encontrarnos con rutas como /PendingInvoices/ViewAll
para acceder a la siguiente acción:
public class PendingInvoicesController : Controller
{
public IActionResult ViewAll() => Content("Show all pending invoices");
}
Lo mismo ocurre con páginas Razor. Si usamos las rutas por defecto, al archivo /Pages/ShowAllPendingInvoices.cshtml
podríamos acceder mediante la ruta /ShowAllPendingInvoices
. No es que sean rutas terribles, pero tampoco podemos decir que sean lo mejor del mundo en términos de legibilidad y conveniencia.
El kebab-casing consiste en separar con un guion "-" las distintas palabras que componen los fragmentos de la ruta, por lo que en los casos anteriores tendríamos /pending-invoices/view-all
y show-all-pending-invoices
, algo bastante más legible, elegante, y apropiado desde el punto de vista del SEO.
El nombre kebab-casing viene de que visualmente el resultado es similar a un pincho atravesando trozos de comida. Imaginación que no falte 😉
En este post vamos a ver cómo aprovechar los puntos de extensibilidad del sistema de routing de ASP.NET Core para modificar la forma en que genera rutas y así adaptarlo a nuestras necesidades.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Creando gráficas estadísticas en Blazor con los componentes visuales de Syncfusion
José María Aguilar - 30 Leyes epónimas relacionadas con el desarrollo de software (I)
José María Aguilar
.NET Core / .NET
- Introducing the New T4 Command-Line Tool for .NET
Mike Corsaro - Seamless Integration Testing With WireMock.NET
Code Maze - C# 12: Collection literals
Steven Giesel - Wolverine 1.0 is Out! & Wolverine’s Middleware Strategy is a Different Animal
Jeremy D. Miller - Differences Between ExpandoObject, DynamicObject and dynamic
Code Maze - How to use RuntimeHelpers.IsReferenceOrContainsReferences to micro-optimize collections
Gérald Barré - C# Source Code Generators
Bruno Sonnino - C# Struct vs Class: Decoding Key Differences and Use Cases
Wade Gausden - Learn how to mock your HttpClient in C# now with 2 simple methods
Henrique Dalcin Dalmas - Microsoft Forms Service’s Journey to .NET 6
Ray Yao - Validating nested DataAnnotation IOptions recursively with MiniValidation
Andrew Lock - Using StringBuilder To Replace Values
Khalid Abuhakmeh - Parsing websites in C# with Html Agility Pack or AngleSharp
Thomas Ardal - Create your own Mediator (like Mediatr)
Steven Giesel - Getting the .NET Desktop Runtime Installed with a Custom Runtime Checker and Installer
Rick Strahl - Improved .NET Debugging Experience with Source Link
Patrick Smacchia - 7 Things about C#: Running Apps
Joe Mayo - Permutations of a String in C#
Matjaz Prtenjak - Five Reasons Why I Love HangFire
Kevin W. Griffin - Value Objects in C#
Code Maze
Desde la aparición de los nullable reference types, o tipos referencia anulables, en C# 8, nos encontramos frecuentemente con el warning de compilación CS8618, que nos recuerda que las propiedades de tipo referencia definidas como no anulables (es decir, que no pueden contener nulos) deben ser inicializadas obligatoriamente porque de lo contrario contendrán el valor null
, algo que iría en contra de su propia definición.
Para verlo con un ejemplo, consideremos una aplicación de consola con el siguiente código:
var friend = new Friend() {Name = "John", Age = 32};
Console.WriteLine($"Hello, {friend.Name}");
public class Friend
{
public string Name { get; set; }
public int Age { get; set; }
}
La aplicación se ejecutará sin problema, aunque al compilarla obtendremos el warning CS8618:
D:\Projects\ConsoleApp78>dotnet build
MSBuild version 17.4.1+9a89d02ff for .NET
Determining projects to restore...
Restored D:\Projects\ConsoleApp78\ConsoleApp78.csproj (in 80 ms).
D:\Projects\ConsoleApp78\Program.cs(8,19): warning CS8618: Non-nullable property 'Name'
must contain a non-null value when exiting constructor. Consider declaring the
property as nullable.
[...]
[D:\Projects\ConsoleApp78\ConsoleApp78.csproj]
1 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.63
D:\Projects\ConsoleApp78\ConsoleApp78>_
También en Visual Studio podremos ver el subrayado marcando la propiedad como incorrecta:
Aunque muchas veces este warning viene bien porque nos ayudará a evitar errores, hay otras ocasiones en las que puede llegar a ser molesta tanta insistencia. Y en estos casos, ¿cómo podemos librarnos de este aviso?
Disclaimer: algunas de las soluciones mostradas no son especialmente recomendables, o incluso no tienen sentido en la práctica, pero seguro que son útiles para ver características de uso poco habitual en C#.
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Crear manualmente instancias de clases usando el proveedor de servicios de .NET
José María Aguilar - PremoniSense, la gran novedad de Visual Studio 2010
José María Aguilar
(¿No era este post una premonición en sí mismo? :D)
.NET Core / .NET
- Announcing .NET 8 Preview 5
Jiachen Jiang - 12: Primary constructor on classes and struct
Anthony Giretti - Optional DependencyInjection in .NET
Federico Alterio - Introduction to Firebase in .NET
Phil Broderick - Collatz sequences by function composition
Mark Seemann - C# Tip: Use custom Equality comparers in Nunit tests
Davide Bellone - How does List work under the hood in .NET?
Steven Giesel - How to detect heap allocations
Bart Wullems
Ya he comentado alguna vez que el hecho de trabajar a diario con C# no implica que conozcamos todas sus funcionalidades, detalles, trampas y recovecos. Después de muchos años, yo sigo encontrándome sorpresas bastante a menudo.
Hace poco, andaba haciendo algunas pruebas y llegué a un código como el siguiente:
var a = 1;
var (b, c) = 4;
var (d, e, f) = 9;
Console.WriteLine(a + b + c + d + e + f ); // Muestra por consola "14"
Así al vistazo, diréis que el código no compila tal cual, pero la pregunta es: ¿sería posible que compilara y, además, mostrara la salida que pretendemos sin tocar una sola línea de las que vemos ahí?
Si lo pensáis un poco seguro que podéis responder a las preguntas. Y si no, pulsad aquí para ver la solución 👇👇
Pues en efecto, el código tal y como está no compila, así que debemos pasar a la siguiente parte de la pregunta: qué podemos hacer para que compile y, además, muestre por consola el valor que buscamos, sin tocar ni una coma de esas cuatro líneas de código propuesto como punto de partida.
Si nos fijamos bien, la primera línea es una asignación normal, pero en la segunda y tercera línea estamos asignando valores a variables usando sintaxis propia de tuplas. En el fondo, ambas líneas son iguales, y fallan en compilación porque no podemos asignar un entero a un tupla. ¿O quizás sí?
Si recordáis, hace mucho tiempo hablamos por aquí de la deconstrucción de clases, un interesante mecanismo que, al más puro estilo de cheff sofisticado, permitía deconstruir o descomponer objetos en tuplas, simplemente implementando el método Deconstruct()
.
Pues bien, resulta que este método Deconstruct()
puede implementarse de forma externa al tipo que va a ser deconstruido mediante extension methods. Seguro que ya empezáis a ver por dónde van los tiros... 😉 En efecto, podríamos implementar el método extensor Deconstruct()
sobre el tipo int
e introducir en él la lógica que nos interese.
Una posible implementación sería la siguiente, en la que tenemos sobrecargas de Deconstruct()
para dos y tres parámetros de salida, entre los que repartimos equitativamente el valor del entero a deconstruir:
public static class IntegerExtensions
{
public static void Deconstruct(this int i, out int i1, out int i2)
{
(i1, i2) = (i / 2, i / 2);
}
public static void Deconstruct(this int i, out int i1, out int i2, out int i3)
{
(i1, i2, i3) = (i / 3, i / 3, i / 3);
}
}
Si ejecutamos ahora mentalmente el código propuesto, veremos que se cumplen los requisitos iniciales:
var a = 1; // a=1
var (b, c) = 4; // "4" se deconstruye en (2,2). Por tanto: b=c=2
var (d, e, f) = 9; // "9" se deconstruye en (3,3,3). Por tanto, d=e=f=3
Console.WriteLine(a + b + c + d + e + f ); //
1+2+2+3+3+3 -> Muestra "14":
Bonito y maquiavélico uso de tuplas y deconstrucción, ¿verdad? 😉