Novedades de las bibliotecas de .NET para .NET 11

En este artículo se describen las nuevas características de las bibliotecas de .NET para .NET 11. Se actualizó por última vez para la versión preliminar 4.

Diagnóstico y ejecución de procesos

Expansión de API de procesos

Process tiene un conjunto sustancial de nuevas API que cubren escenarios comunes en los que anteriormente tenía que conectar OutputDataReceived/ErrorDataReceived eventos manualmente o usar P/Invoke.

Asistentes de ejecución y captura

Las nuevas API one-shot le permiten iniciar un proceso y obtener su resultado sin configuración manual:

// One-shot capture: stdout and stderr together, plus exit code.
ProcessTextOutput result = await Process.RunAndCaptureTextAsync(
    "git", ["status", "--porcelain"]);

Console.WriteLine(result.StandardOutput);
Console.WriteLine($"Exit code: {result.ExitStatus.ExitCode}");

El conjunto completo de asistentes incluye:

Lanzamientos de tipo «dispara y olvida»

  • Process.StartAndForget — inicia un proceso secundario cuando no tiene intención de esperarlo; el tiempo de ejecución desasocia automáticamente el identificador.
  • ProcessStartInfo.StartDetached : se desasocia de la sesión o consola del elemento primario para que el elemento secundario pueda sobrevivir a una salida del terminal.
  • ProcessStartInfo.KillOnParentExit (solo Windows): el elemento secundario finaliza cuando se cierra el proceso primario.

Métodos de ciclo de vida SafeProcessHandle

SafeProcessHandle obtiene métodos de ciclo de vida para escenarios avanzados:

Control más preciso del mango

Compatibilidad con FORCE_COLOR de consola

La salida de la consola de .NET ahora admite el estándar FORCE_COLOR, además de la compatibilidad existente con NO_COLOR. Cuando FORCE_COLOR se establece, Console.IsOutputRedirected ya no suprime los códigos de escape ANSI. Esto resulta útil cuando canaliza la salida de dotnet run a través de tee, a un visor de registros de CI o a través de less -R:

FORCE_COLOR=1 dotnet run | tee build.log

Control de texto, serialización y datos

Mejoras de cadenas y caracteres

.NET 11 presenta mejoras significativas en las API de manipulación de cadenas y caracteres, lo que facilita el trabajo con caracteres Unicode y runes.

Soporte para rune en métodos String

La String clase ahora incluye métodos que aceptan Rune parámetros, lo que le permite buscar, reemplazar y manipular cadenas mediante valores escalares Unicode directamente. Estos nuevos métodos incluyen:

Muchos de estos métodos incluyen sobrecargas que aceptan un parámetro StringComparison para comparaciones culturalmente conscientes.

Char.Es igual con StringComparison

La Char estructura ahora incluye un Char.Equals(Char, StringComparison) método que acepta un StringComparison parámetro, permitiéndote comparar personajes usando comparaciones culturales o ordinales.

Compatibilidad con la runa en TextInfo

La TextInfo clase ahora proporciona TextInfo.ToLower(Rune) métodos TextInfo.ToUpper(Rune) que aceptan Rune parámetros, permitiéndote realizar conversiones de casos sobre valores escalares Unicode individuales.

Mejoras de codificación en Base64

.NET 11 agrega nuevas API y sobrecargas al tipo de Base64 existente, lo que proporciona compatibilidad completa con la codificación y descodificación de Base64. Estas adiciones ofrecen un rendimiento y flexibilidad mejorados en comparación con los métodos existentes.

Nuevas API de Base64

Las nuevas API admiten operaciones de codificación y descodificación con varios formatos de entrada y salida:

Estos métodos proporcionan métodos de conveniencia de alto nivel (que asignan y devuelven matrices o cadenas) y métodos basados en intervalos de bajo nivel (para escenarios de asignación cero).

System.Text.Unicode tiene dos nuevas características complementarias. Utf16.IsValid(ReadOnlySpan<Char>) responde si una secuencia tiene un formato correcto UTF-16 sin examinar dos veces y Utf8.IndexOfInvalidSubsequence(ReadOnlySpan<Byte>) / Utf16.IndexOfInvalidSubsequence(ReadOnlySpan<Char>) devuelve la posición de la primera secuencia de unidad de código con formato incorrecto (o -1 para la entrada válida). Juntos, estos métodos permiten que los analizadores, los validadores y los serializadores notifiquen errores precisos en lugar de mensajes genéricos de error de codificación.

ReadOnlySpan<byte> bytes = [0xC3, 0x28]; // invalid UTF-8
int badIndex = Utf8.IndexOfInvalidSubsequence(bytes); // 0

ReadOnlySpan<char> chars = "valid \uD83D\uDC4D end"; // valid UTF-16 (👍 emoji)
bool ok = Utf16.IsValid(chars); // true

Mejoras de System.Text.Json

Recuperación de información de tipo genérico

Un patrón común al trabajar con metadatos del tipo System.Text.Json consiste en recuperar un JsonTypeInfo<T> de JsonSerializerOptions. Antes, tenías que hacer downcast manualmente desde el método no genérico GetTypeInfo(Type) . Los nuevos métodos genéricos JsonSerializerOptions.GetTypeInfo<T>()JsonSerializerOptions.TryGetTypeInfo<T>(JsonTypeInfo<T>) y métodos devuelven metadatos fuertemente tipados directamente, eliminando el cast.

JsonSerializerOptions options = new(JsonSerializerDefaults.Web);
options.MakeReadOnly();

// Before: manual downcast required
JsonTypeInfo<MyRecord> info1 = (JsonTypeInfo<MyRecord>)options.GetTypeInfo(typeof(MyRecord));

// After: generic method returns the right type directly
JsonTypeInfo<MyRecord> info2 = options.GetTypeInfo<MyRecord>();

// TryGetTypeInfo variant for cases where the type may not be registered
if (options.TryGetTypeInfo<MyRecord>(out JsonTypeInfo<MyRecord>? typeInfo))
{
    // Use typeInfo
    _ = typeInfo;
}

Esto es especialmente útil cuando se trabaja con escenarios de generación de origen, NativeAOT y serialización polimórfica en los que el acceso a metadatos de tipo es común.

Nombrar e ignorar los valores predeterminados

Las opciones de nomenclatura y para ignorar disponibles en System.Text.Json ahora incluyen:

  • JsonNamingPolicy.PascalCase: Una nueva política de nombres incorporada que convierte los nombres de propiedades a PascalCase. Se une a las políticas existentes de camelCase, snake_case y kebab-case.
  • Directiva de nomenclatura por miembro: el nuevo System.Text.Json.Serialization.JsonNamingPolicyAttribute atributo le permite invalidar la directiva de nomenclatura en propiedades o campos individuales, lo que proporciona un control específico sin un convertidor personalizado.
  • Condiciones de omisión de nivel de tipo: la aplicación System.Text.Json.Serialization.JsonIgnoreAttribute en el nivel de clase o estructura establece el comportamiento de omitir predeterminado para todos los miembros, por lo que ya no es necesario repetir el atributo en cada propiedad que acepta valores NULL.
// Type-level JsonIgnore: all members use WhenWritingNull by default
// Per-member JsonNamingPolicy: EventName uses camelCase even though the
// serializer options use PascalCase
var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.PascalCase
};

var data = new EventData { EventName = "Launch", Notes = null };
string json = JsonSerializer.Serialize(data, options);
Console.WriteLine(json);
// {"eventName":"Launch"}  -- Notes omitted (null), EventName camel-cased

Compatibilidad con uniones discriminadas de F#

El serializador ahora admite de forma nativa las uniones discriminadas de F#. Las aplicaciones que comparten tipos entre productores de F# y consumidores de C# ya no necesitan un convertidor personalizado para las formas más comunes:

type Shape =
    | Circle of radius: float
    | Square of side: float

let json = System.Text.Json.JsonSerializer.Serialize(Circle 1.5)
// {"$type":"Circle","radius":1.5}

Utf8JsonWriter.Reset con opciones

Reset ahora acepta un JsonWriterOptions parámetro, por lo que las instancias de escritor se pueden volver a agrupar con diferentes opciones sin asignar un nuevo escritor:

using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true });
writer.WriteStartObject();
writer.WriteString("name", "example");
writer.WriteEndObject();
writer.Flush();

// Reset with different options for next use — no new allocation needed
stream.SetLength(0);
writer.Reset(stream, new JsonWriterOptions { Indented = false });

Mejoras de expresiones regulares

Opción de AnyNewLine

Un nuevo RegexOptions.AnyNewLine indicador hace que ^, $ y . consideren el conjunto completo de caracteres Unicode de nueva línea como terminadores de línea, no solo \n. Esto ayuda a analizar texto que combina Windows (\r\n), Unix (\n) y finales de línea específicos de Unicode (\u0085, \u2028, \u2029).

string text = "line1\r\nline2\u0085line3\u2028line4";

// RegexOptions.AnyNewLine makes ^, $, and . treat all Unicode newline
// sequences as line terminators, not just \n.
MatchCollection matches = Regex.Matches(
    text,
    @"^line\d$",
    RegexOptions.Multiline | RegexOptions.AnyNewLine);

Console.WriteLine(matches.Count); // 4

Correcciones del motor regex y del generador de origen

.NET 11 incluye varias correcciones relacionadas con la exactitud de las expresiones regulares y la calidad del código:

  • El motor sin retroceso ya no tarda un tiempo superlineal en determinados patrones de bucles anidados y produce resultados correctos en casos en los que antes divergía.
  • El compilador de expresiones regulares y el generador de código fuente procesan resumeAt correctamente cuando aparece un condicional dentro del cuerpo de un bucle.
  • El solucionador de código SYSLIB1045 ya no crea nombres de clase duplicados cuando se aplican en varias declaraciones parciales de la misma clase.

Formatos de compresión y archivo

Mejoras de compresión

.NET 11 incluye varias mejoras en las API de compresión.

Modos de acceso a elementos de archivos ZIP

La ZipArchiveEntry clase ahora admite la apertura de entradas con modos de acceso a archivos específicos a través de nuevas sobrecargas: ZipArchiveEntry.Open(FileAccess) y ZipArchiveEntry.OpenAsync(FileAccess, CancellationToken). Estas sobrecargas aceptan un FileAccess parámetro y permiten abrir entradas ZIP para acceso de lectura, escritura o lectura-escritura.

Además, una nueva CompressionMethod propiedad expone el método de compresión usado para una entrada a través de la ZipCompressionMethod enumeración , que incluye valores para Stored, Deflatey Deflate64.

Validación ZIP CRC32

ZipArchive valida la suma de comprobación CRC32 al leer entradas ZIP. Los archivos dañados o truncados que anteriormente pasaban sin errores ahora producen InvalidDataException, lo que le ayuda a detectar problemas de integridad de datos desde el principio.

Cambio de comportamiento de DeflateStream y GZipStream

Empezando en .NET 11, DeflateStream y GZipStream siempre escribe cabeceras y pies de página en el flujo de salida, incluso cuando no se escribe ningún dato. Esto garantiza que la salida sea una secuencia comprimida válida según las especificaciones Deflate y GZip.

Anteriormente, estos flujos no generaron ninguna salida si no se escribió ningún dato, lo que da lugar a un flujo de salida vacío. Este cambio garantiza la compatibilidad con herramientas que esperan flujos comprimidos con formato correcto.

Para más información, consulte cabeceras y pies de página de escritura DeflateStream y GZipStream para cargaútil vacía.

APIs de Deflate, ZLib y GZip basadas en spans

System.IO.Compression ahora ofrece Span<byte>/ReadOnlySpan<byte> puntos de entrada de codificación y descodificación para los formatos Deflate, ZLib y GZip. Las nuevas API, en tipos como DeflateEncoder, ZLibEncoder y GZipEncoder, reflejan la estructura de BrotliEncoder/BrotliDecoder y las primitivas de Zstandard. Puede comprimir y descomprimir búferes sin asignar un Stream. Esto es útil para escenarios de alto volumen, como analizadores de protocolos, sistemas de envío de registros y middleware que ya operan sobre segmentos.

ReadOnlySpan<byte> source = [0x48, 0x65, 0x6C, 0x6C, 0x6F]; // "Hello"
byte[] buffer = new byte[source.Length + 32];
Span<byte> destination = buffer;

using ZLibEncoder encoder = new();
OperationStatus status = encoder.Compress(
    source, destination, out int bytesConsumed, out int bytesWritten,
    isFinalBlock: true);

Console.WriteLine($"Compressed {bytesConsumed} bytes into {bytesWritten} bytes. Status: {status}");

Compresión Zstandard

Las API de compresión Zstandard, por ejemplo, ZstandardStream y ZstandardEncoder, ahora forman parte del System.IO.Compression espacio de nombres, junto con DeflateStream, GZipStreamy BrotliStream. La superficie de la API permanece sin cambios por lo demás.

Selección de formato de archivo tar

New sobrecarga CreateFromDirectory y CreateFromDirectoryAsync acepta un TarEntryFormat parámetro, dándote control directo sobre el formato de archivo. Anteriormente, CreateFromDirectory siempre producía archivos Pax. Los nuevos sobrecargadores soportan los cuatro formatos tar — Pax, Ustar, GNU y V7 — para compatibilidad con herramientas y entornos específicos.

// Create a GNU format tar archive for Linux compatibility
TarFile.CreateFromDirectory("/source/dir", "/dest/archive.tar",
    includeBaseDirectory: true, format: TarEntryFormat.Gnu);

// Create a Ustar format archive for broader compatibility
using Stream outputStream = File.OpenWrite("/dest/ustar.tar");
TarFile.CreateFromDirectory("/source/dir", outputStream,
    includeBaseDirectory: false, format: TarEntryFormat.Ustar);

// Async version
CancellationToken cancellationToken = CancellationToken.None;
await TarFile.CreateFromDirectoryAsync("/source/dir", "/dest/archive.tar",
    includeBaseDirectory: true, format: TarEntryFormat.Pax,
    cancellationToken: cancellationToken);

TarReader ahora también puede leer entradas que usan la representación dispersa de GNU 1.0 (PAX). La representación anterior de 0.1 ya era compatible. Con la compatibilidad de la versión 1.0 ya implementada, TarReader se ajusta a lo que las implementaciones modernas tar escriben de forma predeterminada para los archivos dispersos.

Colecciones, tipos numéricos y E/S de bajo nivel

Compatibilidad con BFloat16 en BitConverter

La BitConverter clase ahora incluye métodos para convertir entre BFloat16 valores y matrices de bytes o representaciones de bits. Estos nuevos métodos incluyen:

BFloat16 (punto flotante del cerebro) es un formato de punto flotante de 16 bits que se usa normalmente en el aprendizaje automático y la computación científica.

Formato hexadecimal de punto flotante y análisis

double, floaty Half ahora se pueden formatear y analizar en su forma hexadecimal IEEE-754. El formulario hexadecimal conserva cada bit del valor subyacente, lo que lo convierte en la opción adecuada para las pruebas de archivos dorados, la interoperabilidad entre lenguajes con C/C++ printf("%a", ...)y cualquier escenario en el que el recorrido de ida y vuelta de un double texto decimal es demasiado perdido.

double value = Math.PI;

// Format as hexadecimal IEEE-754: preserves all bits exactly
string hex = value.ToString("X"); // e.g., "0X1.921FB54442D18P+1"
double roundTripped = double.Parse(hex, NumberStyles.HexFloat);

Console.WriteLine(roundTripped == value); // True — exact round-trip

Mejoras numéricas

Matrix4x4.GetDeterminant() ahora usa una implementación vectorizada de SSE, lo que mejora el rendimiento aproximadamente 15%.

Mejoras de E/S de bajo nivel

Soporte para canalizaciones SafeFileHandle

SafeFileHandle obtiene dos nuevos miembros:

SafeFileHandle.CreateAnonymousPipe(
    out SafeFileHandle readEnd,
    out SafeFileHandle writeEnd,
    asyncRead: true,
    asyncWrite: false);

using (readEnd)
using (writeEnd)
{
    // SafeFileHandle.Type reports the kind of OS object the handle refers to
    Console.WriteLine(readEnd.Type);   // Pipe
    Console.WriteLine(writeEnd.Type);  // Pipe
}

Compatibilidad con canalizaciones de RandomAccess

RandomAccess.Read y RandomAccess.Write ahora trabajan con asas no buscables como tuberías, además de asas de archivo normales.

En Windows, Process ahora utiliza E/S superpuesta para stdout/stderr redirigido, lo que reduce el bloqueo de pools de hilos en aplicaciones con mucho proceso.

Mejoras de colecciones

BitArray.PopCount

La BitArray clase ahora incluye un BitArray.PopCount() método que devuelve el número de bits establecidos a true en la matriz. Esto proporciona una manera eficaz de contar bits establecidos sin tener que recorrer manualmente la matriz.

Compatibilidad con IReadOnlySet en la serialización JSON

La JsonMetadataServices clase ahora incluye un JsonMetadataServices.CreateIReadOnlySetInfo método, lo que permite la compatibilidad con la serialización JSON para IReadOnlySet<T> las colecciones.

Extensiones y plataforma para desarrolladores

Código auxiliar para unión discriminada

Note

Se trata de una característica en versión preliminar en .NET 11.

.NET 11 presenta System.Runtime.CompilerServices.UnionAttribute y System.Runtime.CompilerServices.IUnion en System.Runtime.CompilerServices. Estos tipos son la parte en tiempo de ejecución del diseño de tipos de unión discriminada de C#. Todavía no están orientados directamente al usuario —el compilador de C# y los generadores de código fuente son quienes previsiblemente los producirán—, pero se incluyen en el framework para que las bibliotecas puedan desarrollar sobre esta superficie de API desde ahora.

Para ver el diseño del lado del lenguaje, consulte la propuesta de uniones de C#.

Adiciones de MetadataLoadContext

MetadataLoadContext.GetLoadContext(Assembly) devuelve el contexto de carga que produjo un determinado Assembly, en paralelo con la API existente desde hace tiempo en AssemblyLoadContext. Esto cubre una carencia en las herramientas que reflejan sobre ensamblados en un MetadataLoadContext aislado y que necesitan volver desde una referencia Assembly hasta el contexto al que pertenece:

using System.Reflection;
using System.Reflection.Metadata;

string[] paths = [typeof(object).Assembly.Location];
using var mlc = new MetadataLoadContext(new PathAssemblyResolver(paths));
Assembly asm = mlc.LoadFromAssemblyPath(typeof(object).Assembly.Location);

MetadataLoadContext owner = MetadataLoadContext.GetLoadContext(asm)!;
Console.WriteLine(ReferenceEquals(owner, mlc)); // true

Constante de esquema de datos de URI

Se ha agregado una nueva Uri.UriSchemeData constante que representa el data: esquema URI. Esta constante proporciona una manera estandarizada de hacer referencia a los URI de datos.

Mejoras de atributos StringSyntax

La StringSyntaxAttribute clase ahora incluye constantes para lenguajes de programación comunes:

Estas constantes se pueden usar con el StringSyntax atributo para proporcionar una mejor compatibilidad con herramientas para literales de cadena que contienen código en estos lenguajes.

Almacenamiento en caché y configuración

Vinculación de configuración

Microsoft.Extensions.Configuration añade Microsoft.Extensions.Configuration.ConfigurationIgnoreAttribute, por lo que los modelos pueden excluir propiedades individuales de la vinculación de forma declarativa sin depender de conmutadores BindNonPublicProperties ni de convertidores personalizados:

public sealed class AppOptions
{
    public string Endpoint { get; set; } = "";

    [ConfigurationIgnore]
    public string ComputedKey => Endpoint + ":default";
}

ConfigurationBinder ahora también enlaza una matriz vacía a un parámetro de constructor en lugar de iniciar.

PhysicalFilesWatcher ya no produce cuando su directorio raíz aún no existe y InMemoryDirectoryInfo resuelve .. y otros segmentos relativos de forma coherente con el proveedor físico.

Métricas de MemoryCache OpenTelemetry

MemoryCache ahora emite un conjunto integrado de métricas compatibles con OpenTelemetry (OTel) sin un paquete de adaptador adicional. Para activarlo, establezca MemoryCacheOptions.TrackStatistics en true:

var cache = new MemoryCache(new MemoryCacheOptions
{
    TrackStatistics = true
});

El nuevo medidor Microsoft.Extensions.Caching.Memory.MemoryCache publica cuatro instrumentos de observación:

  • dotnet.cache.requests (con una dotnet.cache.request.type etiqueta que distingue hit de miss)
  • dotnet.cache.evictions
  • dotnet.cache.entries
  • dotnet.cache.estimated_size

Pase un System.Diagnostics.Metrics.IMeterFactory a la nueva sobrecarga del constructor MemoryCache.MemoryCache(IOptions<MemoryCacheOptions>, ILoggerFactory, IMeterFactory) para las métricas por instancia. En su ausencia, los instrumentos se agregan a nivel de proceso en un medidor compartido.

Seguridad de redes y transporte

Refuerzo del intercambio de claves TLS

Dos System.Net.Security elementos mejoran la confiabilidad de TLS (Seguridad de la capa de transporte):

  • SslStream Las correcciones de la comprobación de límites durante el handshake del lado del servidor en TlsFrameHelper corrigen varios casos límite que podían manifestarse como IOException en registros de ClientHello malformados.
  • En Linux, los fallos en la validación de certificados ahora se notifican al homólogo como alertas TLS estándar, en consonancia con el comportamiento de Windows. Los clientes que se conectan reciben un error claro de establecimiento de conexión en lugar de una interrupción de la conexión.

Degradación automática de HTTP/2 para la autenticación de Windows

HttpClient se degrada automáticamente a HTTP/1.1 cuando una solicitud requiere autenticación de Windows (NTLM/Negotiate) sobre HTTP/2. La especificación HTTP/2 no permite los esquemas de autenticación enlazados a la conexión en los que se basan NTLM y Kerberos, por lo que estas solicitudes han fallado anteriormente. Con la degradación aplicada, las aplicaciones dirigidas a entornos de autenticación mixta—habituales en las intranets empresariales—funcionan sin anulaciones explícitas HttpRequestMessage.Version.

Consulte también