Compartir a través de


Novedades de C# 13

C# 13 incluye las siguientes características nuevas. Puede probar estas características con la versión más reciente de visual Studio 2022 o el SDK de .NET 9:

A partir de Visual Studio 17.12, C# 13 incluye la palabra clave contextual field como característica de vista previa.

C# 13 es compatible con .NET 9. Para obtener más información, vea Control de versiones del lenguaje C#.

Puede descargar la última versión del SDK de .NET 9 desde la página de descargas de .NET . También puede descargar visual Studio 2022, que incluye el SDK de .NET 9.

Las nuevas características se agregan a la página "Novedades de C#" cuando están disponibles en versiones preliminares públicas. La sección conjunto de trabajo de la página de estado de características de roslyn realiza un seguimiento cuando se combinan las próximas características en la rama principal.

Puede consultar los cambios importantes introducidos en C# 13 en nuestro artículo sobre cambios importantes.

Nota

Estamos interesados en sus comentarios sobre estas características. Si encuentra problemas con cualquiera de estas nuevas características, cree un nuevo problema en el repositorio dotnet/roslyn.

Colecciones de params

El modificador params no se limita a los tipos de matriz. Ahora puede usar params con cualquier tipo de colección reconocido, incluidos System.Span<T>, System.ReadOnlySpan<T>y tipos que implementan System.Collections.Generic.IEnumerable<T> y tienen un método Add. Además de los tipos concretos, también se pueden usar las interfaces System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.IReadOnlyList<T>, System.Collections.Generic.ICollection<T>y System.Collections.Generic.IList<T>.

Cuando se usa un tipo de interfaz, el compilador sintetiza el almacenamiento de los argumentos proporcionados. Puede obtener más información en la especificación de funciones para las colecciones params.

Por ejemplo, las declaraciones de método pueden declarar intervalos como parámetros params:

public void Concat<T>(params ReadOnlySpan<T> items)
{
    for (int i = 0; i < items.Length; i++)
    {
        Console.Write(items[i]);
        Console.Write(" ");
    }
    Console.WriteLine();
}

Nuevo objeto de bloqueo

El entorno de ejecución de .NET 9 incluye un nuevo tipo para la sincronización de subprocesos, el tipo de System.Threading.Lock. Este tipo proporciona una mejor sincronización de subprocesos a través de su API. El método Lock.EnterScope() entra en un ámbito exclusivo. El ref struct devuelto que admite el patrón Dispose() para salir del ámbito exclusivo.

La instrucción lock de C# reconoce si el destino del bloqueo es un objeto Lock. Si es así, usa la API actualizada, en lugar de la API tradicional mediante System.Threading.Monitor. El compilador también reconoce si convierte un objeto Lock a otro tipo y se generaría el código basado en Monitor. Puede consultar más detalles en la especificación de la funcionalidad del nuevo objeto de bloqueo.

Esta funcionalidad le permite obtener las ventajas del nuevo tipo de biblioteca cambiando el tipo de objeto que lock. No es necesario cambiar ningún otro código.

Nueva secuencia de escape

Puede usar \e como una secuencia de escape literal de caracteres para el carácter de ESCAPE (U+001B en unicode). Anteriormente, se usaba \u001b o \x1b. No se recomienda usar \x1b porque si los siguientes caracteres siguientes 1b eran dígitos hexadecimales válidos, esos caracteres se convirtieron en parte de la secuencia de escape.

Tipos naturales de grupo de métodos

Esta característica realiza pequeñas optimizaciones para solucionar sobrecargas con grupos de métodos. Un grupo de métodos consiste en un método y todas las sobrecargas con el mismo nombre. El comportamiento anterior era para que el compilador construya el conjunto completo de métodos candidatos para un grupo de métodos. Si se necesitaba un tipo natural, el tipo natural se determinó a partir del conjunto completo de métodos candidatos.

El nuevo comportamiento consiste en eliminar el conjunto de métodos candidatos en cada ámbito, quitando los métodos candidatos que no son aplicables. Normalmente, los métodos eliminados son métodos genéricos con una aridad incorrecta o cuyos requisitos no se cumplen. El proceso continúa hasta el siguiente ámbito externo solo si no se encuentra ningún método candidato. Este proceso sigue más detenidamente el algoritmo general para la resolución de sobrecargas. Si todos los métodos candidatos encontrados en un ámbito determinado no coinciden, el grupo de métodos no tiene un tipo natural.

Puede leer los detalles de los cambios en la especificación de la propuesta .

Acceso a índices implícitos

El operador de índice implícito "from the end", ^, ahora se permite en una expresión de inicializador de objeto. Por ejemplo, ahora puede inicializar una matriz en un inicializador de objeto como se muestra en el código siguiente:

public class TimerRemaining
{
    public int[] buffer { get; set; } = new int[10];
}

var countdown = new TimerRemaining()
{
    buffer =
    {
        [^1] = 0,
        [^2] = 1,
        [^3] = 2,
        [^4] = 3,
        [^5] = 4,
        [^6] = 5,
        [^7] = 6,
        [^8] = 7,
        [^9] = 8,
        [^10] = 9
    }
};

La clase TimerRemaining incluye una matriz buffer inicializada a una longitud de 10. En el ejemplo anterior se asignan valores a este array mediante el operador de índice "desde el final" (^), creando de manera efectiva un array que cuenta de 9 a 0.

En versiones anteriores a C# 13, el operador ^ no se puede usar en un inicializador de objeto. Debe indexar los elementos desde el principio.

ref y unsafe en iteradores y métodos de async

Esta característica y las dos características siguientes permiten que los tipos de ref struct usen nuevas construcciones. No los usará a menos que escriba sus propios tipos ref struct. Lo más probable es que veas una ventaja indirecta ya que System.Span<T> y System.ReadOnlySpan<T> obtengan más funcionalidad.

Antes de C# 13, los métodos de iterador (métodos que usan yield return) y async métodos no podían declarar variables ref locales ni podían tener un contexto de unsafe.

En C# 13, los métodos async pueden declarar variables locales ref o variables locales de tipo ref struct. Sin embargo, no se puede acceder a esas variables a través de un límite de await. Tampoco se puede acceder a estos a través de un límite de yield return.

Esta relajación de la restricción permite al compilador admitir el uso seguro comprobable de variables locales ref y tipos de ref struct en más contextos. Puede usar de forma segura tipos como System.ReadOnlySpan<T> en estos métodos. El compilador le indica si infringe las reglas de seguridad.

De la misma manera, C# 13 permite contextos unsafe en métodos iteradores. Sin embargo, todas las declaraciones yield return y yield break deben estar en contextos seguros.

allows ref struct

Antes de C# 13, los tipos de ref struct no se podían declarar como argumento de tipo para un tipo o método genéricos. Ahora, las declaraciones de tipos genéricos pueden agregar una antirestricción, allows ref struct. Esta anti-restricción declara que el argumento de tipo proporcionado para ese parámetro de tipo puede ser de tipo ref struct. El compilador aplica reglas de seguridad de referencia en todas las instancias de ese parámetro de tipo.

Por ejemplo, puede declarar un tipo genérico como el código siguiente:

public class C<T> where T : allows ref struct
{
    // Use T as a ref struct:
    public void M(scoped T p)
    {
        // The parameter p must follow ref safety rules
    }
}

Esto permite usar tipos como System.Span<T> y System.ReadOnlySpan<T> con algoritmos genéricos, si procede. Puede obtener más información en las actualizaciones para where y en el artículo de la guía de programación sobre restricciones genéricas .

Interfaces ref struct

Antes de C# 13, los tipos de ref struct no podían implementar interfaces. A partir de C# 13, sí pueden. Puede declarar que el tipo ref struct implementa una interfaz. Sin embargo, para garantizar las reglas de seguridad de ref, no se puede convertir un tipo ref struct en un tipo de interfaz. Esa conversión es una conversión de clase boxing y podría vulnerar la seguridad de ref. Desde esa regla, los tipos de ref struct no pueden declarar métodos que implementen explícitamente un método de interfaz. Además, los tipos de ref struct deben implementar todos los métodos declarados en una interfaz, incluidos esos métodos con una implementación predeterminada.

Obtenga más información en las actualizaciones sobre los tipos ref struct.

Más miembros parciales

Puede declarar propiedades partial e indizadores partial en C# 13. Las propiedades parciales y los indexadores suelen seguir las mismas reglas que los métodos partial: se crea una declaración declaratoria y una declaración de implementación. Las firmas de las dos declaraciones deben coincidir. No obstante, hay una restricción: se puede usar una declaración de propiedad automática para implementar una propiedad parcial. A las propiedades que no declaran un cuerpo se las considera la declaración declaratoria.

public partial class C
{
    // Declaring declaration
    public partial string Name { get; set; }
}

public partial class C
{
    // implementation declaration:
    private string _name;
    public partial string Name
    {
        get => _name;
        set => _name = value;
    }
}

Puede obtener más información en el artículo sobre miembros parciales.

Prioridad de resolución de sobrecarga

En C# 13, el compilador reconoce el OverloadResolutionPriorityAttribute para preferir una sobrecarga sobre otra. Los autores de bibliotecas pueden usar este atributo para asegurarse de que se prefiere una sobrecarga nueva y mejor sobre una sobrecarga existente. Por ejemplo, puede agregar una nueva sobrecarga con mejor rendimiento. No desea interrumpir el código existente que usa la biblioteca, pero quiere que los usuarios actualicen a la nueva versión cuando se vuelvan a compilar. Puede usar Prioridad de resolución de sobrecarga para informar al compilador sobre qué sobrecarga es prioritaria. Se prefieren las sobrecargas con la prioridad más alta.

Esta característica está pensada para que los autores de bibliotecas eviten ambigüedad al agregar nuevas sobrecargas. Los autores de bibliotecas deben usar cuidado con este atributo para evitar confusiones.

Palabra clave field

La palabra clave contextual field está en C# 13 como característica de vista previa. El token field accede al campo auxiliar sintetizado por el compilador en un descriptor de acceso de propiedad. Permite escribir un cuerpo del descriptor de acceso sin declarar un campo auxiliar explícito en la declaración del tipo. Puede declarar un cuerpo para uno o ambos descriptores de acceso en una propiedad auxiliar de campo.

La característica field se publica como una característica en versión preliminar. Queremos aprender de sus experiencias con ella. Es posible que hay cambio importante o se produzca cierta confusión al leer el código en tipos que también incluyen un campo llamado field. Puede usar @field o this.field para desambiguar entre la palabra clave field y el identificador.

Importante

La palabra clave field es una característica en versión preliminar de C# 13. Debe usar .NET 9 y establecer el elemento <LangVersion> en preview en el archivo de proyecto para poder usar la palabra clave contextual field.

Debe tener cuidado con el uso de la característica de palabra clave field en una clase que tenga un campo denominado field. La nueva palabra clave field sombrea un campo denominado field en el ámbito de un descriptor de acceso de propiedad. Puede cambiar el nombre de la variable field o usar el token de @ para hacer referencia al identificador de field como @field. Para obtener más información, consulte la especificación de la función de la palabra clave field.

Si prueba esta funcionalidad y tiene algo que comentar, inclúyalos en la incidencia sobre la funcionalidad en el repositorio csharplang.

Consulte también