Poco a poco vamos haciéndonos con las novedades de C# 12, y en esta ocasión nos centraremos en una nueva sintaxis que proporciona una forma concisa y rápida para declarar los elementos de una colección.
Ya os adelanto que si sois de los que siempre han envidiado otros lenguajes por la facilidad con la que se declaran los elementos de un colección o array, estáis de enhorabuena ;) Porque, sin duda, hay formas de hacerlo menos verbosas que las que hemos tenido hasta ahora en C#:
// JavaScript:
let numbers = [1, 2, 3];
// Python:
numbers = [1, 2, 3]
// PHP:
$array = [1, 2, 3];
// Rust:
let array = [1, 2, 3];
En C# 11 y anteriores, la creación de un array es normalmente más farragosa, porque de alguna forma u otra requiere que especifiquemos que se trata de un nuevo array y, si la inferencia no lo permite, el tipo de los elementos que contendrá:
// Forma verbosa y redundante:
int[] arr1 = new int[3] { 1, 2, 3 };
// Forma clásica, usando 'var' y especificando número y tipo elementos:
var arr2 = new int[3] { 1, 2, 3 };
// Dejamos que el compilador detecte el número de elementos:
var arr3 = new int[] { 1, 2, 3 };
// Dejamos que la inferencia de tipos determine el tipo de los elementos:
var arr4 = new [] { 1, 2, 3 };
// O bien, la más concisa, usando la sintaxis con llaves (sólo válida para arrays):
int[] arr5 = { 1, 2, 3 };
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Archivos JavaScript independientes por componente en Blazor
José María Aguilar - Las 20 mejores tiras cómicas sobre desarrollo de software
José María Aguilar
.NET Core / .NET
- Hardware Intrinsics in .NET 8
Tanner Gooding - Tuple Aliases in C#
Aditi Saxena - Where C# Primary Constructors Make Sense
Steve Smith - A Generic Implementation of Dijkstra’s Smoothsort in C#
Jorge Luis Orejel - 5 Things You Need to Know About Aspire and .NET 8
Growth Acceleration Partners - Redacting sensitive data in logs with Microsoft.Extensions.Compliance.Redaction
Andrew Lock - Hosted service has a major update to its lifecycle events
David Grace - 4 ways to create Unit Tests without Interfaces in C#
Davide Bellone - Build Performance Evaluation Workflow with WorkflowEngine in .NET
Aram Tchekrekjian - How to Decode JWT Tokens in .NET
Muhammad Afzal Qureshi - Generic Type Construction With Static Virtual Interface Members
Brant Burnett - Select a Dropdown Option Using Selenium WebDriver in C#
Semir Teskeredzic - C#– Record types copy constructor
Bart Wullems - All Purpose Object Updater
James Curran
Los records son una interesante fórmula para definir tipos en C# de forma rápida gracias a su concisa sintaxis, además de ofrecer otras ventajas, entre las que destacan la inmutabilidad o la implementación automática de métodos como Equals()
, GetHashCode()
o ToString()
.
Por si no tenéis esto muy fresco, aquí va un ejemplo de record y la clase tradicional equivalente en C#:
// Record:
public record Person(string FirstName, string LastName);
// Clase equivalente (generada automáticamente):
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public override bool Equals(object obj)
{
return obj is Person person &&
FirstName == person.FirstName &&
LastName == person.LastName;
}
public override int GetHashCode()
{
return HashCode.Combine(FirstName, LastName);
}
public Person With(string FirstName = null, string LastName = null)
{
return new Person(FirstName ?? this.FirstName, LastName ?? this.LastName);
}
public void Deconstruct(out string firstName, out string lastName)
{
firstName = this.FirstName;
lastName = this.LastName;
}
}
Como podéis comprobar, hay pocas características de C# que ofrezcan una relación código/funcionalidad tan bárbara como los records. Por ello, poco a poco van ganando popularidad y comenzamos a verlos ya de forma habitual en código propio y ajeno.
Sin embargo, su concisa sintaxis hacen que a veces no sea fácil intuir cómo resolver algunos escenarios que, usando las clases tradicionales, serían triviales.
Por ejemplo, hoy vamos a centrarnos en un escenario muy concreto pero frecuente, cuya solución seguro que veis que puede ser aplicada en otros casos: ya que en los records no definimos propiedades de forma explícita, ¿cómo podríamos aplicarles atributos?
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Llamemos a las cosas por su nombre
José María Aguilar - ASP.NET Core 6, ¿dónde está mi middleware DeveloperExceptionPage?
José María Aguilar
.NET Core / .NET
- .NET 8 Networking Improvements
Máňa & Natalia Kondratyeva - Extending WebAssembly to the Cloud with .NET
Richard Lander - Local Functions in C#
Code Maze - How to Take Advantage of CSharp Optional Parameters for Cleaner Code
Nick Cosentino - How .NET 8.0 boosted JSON Schema performance by 20%
Matthew Adams - Enriching logs with [TagProvider] and ILogEnricher
Andrew Lock - How to use Regular Expressions and Match Evaluators in .NET
Khalid Abuhakmeh - Inline Snapshot testing in .NET
Gérald Barré - Data annotations has some awesome additions in .NET 8
David Grace - Deep C# - Casting the Escape from Strong Typing
Mike James - Learn .NET 8 with New Beginner Videos
Katie Savage - Create Better Looking Console Applications With Spectre.Console
Januarius Njoku - Byte array as a dictionary key? Trying out some options
João Antunes - How to Switch Between .NET SDK Versions
Lennart Pries - .NET Native AOT Explained
NDepend - How to Rename Files in a Folder in C#
Caleb Okechukwu - How to Debug LINQ queries in C#
Michael Shpilt
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Cómo saber si un tipo está registrado en el proveedor de servicios de .NET 6, pero sin necesidad de resolverlo
José María Aguilar - Introducción a SignalR (I): Conceptos básicos
José María Aguilar
.NET Core / .NET
- C# 12: todo lo nuevo del lenguaje aparecido con .NET 8
José Manuel Alarcón - Creating Microsoft Teams Applications with Visual Studio and .NET
Anuraj Parameswaran - How to Check if a File Is in Use With C#
Code Maze - Sep 0.3.0 - Unescape Support (still the Most Efficient .NET CSV Parser)
Niels Rasmussen - 5 Awesome C# Refactoring Tips
Milan Jovanović - Behind [LogProperties] and the new telemetry logging source generator
Andrew Lock - Scriban for Text and Liquid Templating in .NET
Khalid Abuhakmeh - Primary constructors has caused concerns for C# developers
David Grace - Embedding a minimal ASP.NET Web Server into a Desktop Application
Rick Strahl - Building resilient cloud services with .NET 8
Martin Tomka - A journey about the new interceptors of .NET 8
Steven Giesel - TDD and refactoring to patterns in C#: how to write a cron parser
Nicolas Descartes - How to Determine the Operating System in .NET Core
Code Maze - How to make libraries compatible with native AOT
Eric Erhardt - Intercepting HTTP requests with a DelegatingHandler
Tim Deschryver - In Defence of Doubles
Anthony Lloyd
Como sabéis, hasta ahora, los componentes Blazor podían ejecutarse en dos tipos de hosting distintos, Blazor Server y Blazor WebAssembly. Aunque cada uno tiene sus escenarios ideales de uso, ambos enfoques conseguían lo mismo, implementar Single Page Applications en C#, sin necesidad de utilizar JavaScript (bueno, o al menos, minimizando radicalmente su uso):
- Con Blazor Server, se mantiene en el servidor una copia del DOM de cada usuario conectado, de forma que C# puede manipularlo directamente. Luego, mediante una conexión websockets, se sincronizan los cambios con el cliente.
- Blazor WebAssembly lleva al navegador el runtime de .NET, las bibliotecas base y los ensamblados de la aplicación, por lo que todo se ejecuta directamente en el lado cliente gracias a WebAssembly.
Estas dos formas de ejecutar componentes son muy apropiadas cuando se trata de elementos interactivos, capaces de responder a eventos de usuarios y con capacidad de actualizar el contenido de la página. Sin embargo, son muy poco eficientes cuando se trata de páginas estáticas que no requieren interacción con el usuario:
-
Para poder mostrar en el navegador un contenido, en Blazor Server hay que esperar a que el lado cliente descargue la página contenedora, un archivo JavaScript y se establezca la conexión websockets con el servidor, tras lo cual se enviará el contenido de la página.
-
En Blazor WebAssembly, el cliente debe descargar la página contenedora, los ensamblados y todo el entorno de ejecución de .NET y lanzarlo todo sobre WebAssembly. En este momento se puede mostrar el contenido de la página.