Novedades de C# 11
Se agregaron las siguientes características en C# 11:
- Literales de cadena sin formato
- Compatibilidad con matemáticas genéricas
- Atributos genéricos
- Literales de cadena UTF-8
- Nuevas líneas en expresiones de interpolación de cadenas
- Patrones de lista
- Tipos locales de archivo
- Miembros requeridos
- Structs predeterminados automáticos
- Coincidencia de patrones de
Span<char>
en unastring
de constante - Ámbito
nameof
ampliado - IntPtr numérico
- Campos
ref
yscoped ref
- Conversión mejorada de grupo de métodos a delegado
- Ola de advertencias 7
C# 11 es compatible con .NET 7. Para obtener más información, vea Control de versiones del lenguaje C#.
Puede descargar el SDK de .NET 7 más reciente de la página de descargas de .NET. También puede descargar Visual Studio 2022, que incluye el SDK de .NET 7.
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.
Atributos genéricos
Puede declarar una clase genérica cuya clase base sea System.Attribute. Esta característica proporciona una sintaxis más cómoda para los atributos que requieren un parámetro System.Type. Antes había que crear un atributo que tomara Type
como parámetro de constructor:
// Before C# 11:
public class TypeAttribute : Attribute
{
public TypeAttribute(Type t) => ParamType = t;
public Type ParamType { get; }
}
Y, para aplicar el atributo, se usa el operador typeof
:
[TypeAttribute(typeof(string))]
public string Method() => default;
Con esta nueva característica, puede crear un atributo genérico en su lugar:
// C# 11 feature:
public class GenericAttribute<T> : Attribute { }
Luego, especifique el parámetro de tipo para usar el atributo:
[GenericAttribute<string>()]
public string Method() => default;
Debe proporcionar todos los parámetros de tipo al aplicar el atributo. En otras palabras, el tipo genérico debe construirse completamente.
En el ejemplo anterior, los paréntesis vacíos ((
y )
) se pueden omitir, ya que el atributo no tiene ningún argumento.
public class GenericType<T>
{
[GenericAttribute<T>()] // Not allowed! generic attributes must be fully constructed types.
public string Method() => default;
}
Los argumentos de tipo deben cumplir las mismas restricciones que el operador typeof
. No se permiten los tipos que requieren anotaciones de metadatos. Por ejemplo, no se permiten los siguientes tipos como parámetro de tipo:
dynamic
string?
(o cualquier tipo de referencia que acepte valores NULL)(int X, int Y)
(o cualquier otro tipo de tupla que use la sintaxis de tupla de C#)
Estos tipos no se representan directamente en los metadatos Incluyen anotaciones que describen el tipo. En todos los casos, se puede usar el tipo subyacente en su lugar:
object
paradynamic
string
en lugar destring?
.ValueTuple<int, int>
en lugar de(int X, int Y)
.
Compatibilidad matemática genérica
Hay varias características de lenguaje que habilitan la compatibilidad matemática genérica:
static virtual
miembros en interfaces- Operador definido por el usuario checked
- operadores de desplazamiento relajado
- Operador de desplazamiento a la derecha sin signo
Puede agregar static abstract
o static virtual
miembros en interfaces para definir interfaces que incluyan operadores sobrecargables, otros miembros estáticos y propiedades estáticas. El escenario principal de esta característica es usar operadores matemáticos en tipos genéricos. Por ejemplo, puede implementar la interfaz de System.IAdditionOperators<TSelf, TOther, TResult>
en un tipo que implementa operator +
. Otras interfaces definen otras operaciones matemáticas o valores bien definidos. Puede obtener información sobre la nueva sintaxis en el artículo sobre interfaces. Las interfaces que incluyen métodos de static virtual
suelen ser interfaces genéricas. Además, la mayoría declarará una restricción que el parámetro de tipo implementa en la interfaz declarada.
Para más información y probar la característica usted mismo, consulte el tutorial Exploración de miembros de la interfaz abstracta estática o la entrada de blog Características en versión preliminar de .NET 6: matemáticas genéricas.
Las matemáticas genéricas han creado otros requisitos en el lenguaje.
- Operador de desplazamiento a la derecha sin signo: antes de C# 11, para forzar un desplazamiento a la derecha sin signo, había que convertir cualquier tipo entero con signo en un tipo sin signo, llevar a cabo el desplazamiento y, después, convertir el resultado en un tipo con signo. A partir de C# 11, puede usar
>>>
, el operador de desplazamiento sin signo. - Requisitos de operador de desplazamiento menos estrictos: C# 11 elimina el requisito de que el segundo operando debe ser un
int
o convertible implícitamente enint
. Este cambio permite que los tipos que implementan interfaces matemáticas genéricas se usen en estas ubicaciones. - Operadores definidos por el usuario checked y unchecked: los desarrolladores ya pueden definir los operadores aritméticos
checked
yunchecked
. El compilador genera llamadas a la variante correcta en función del contexto actual. Puede obtener más información sobre loschecked
operadores en el artículo sobre operadores aritméticos.
IntPtr
y UIntPtr
numéricos
Los tipos nint
y nuint
ahora se conocen como System.IntPtr y System.UIntPtr respectivamente.
Nuevas líneas en interpolaciones de cadenas
El texto dentro de los caracteres {
y }
de una interpolación de cadenas ahora puede abarcar varias líneas. El texto entre los marcadores {
y }
se analiza como C#. Se permite cualquier C# válido, incluidas las nuevas líneas. Esta característica facilita la lectura de interpolaciones de cadenas que usan expresiones de C# más largas, como expresiones switch
de coincidencia de patrones o consultas LINQ.
Puede aprender más sobre la característica de nuevas líneas en el artículo Interpolaciones de cadenas de la referencia del lenguaje.
Patrones de lista
Los patrones de lista amplían la coincidencia de patrones para buscar coincidencias con secuencias de elementos de una lista o una matriz. Por ejemplo, sequence is [1, 2, 3]
es true
cuando sequence
es una matriz o una lista de tres enteros (1, 2 y 3). Puede hacer coincidir elementos mediante cualquier patrón, como constante, tipo, propiedad y patrones relacionales. El patrón de descarte (_
) coincide con cualquier elemento único y el nuevo patrón de intervalo (..
) coincide con cualquier secuencia de cero o más elementos.
Puede encontrar más información sobre los patrones de lista en el artículo sobre coincidencia de patrones en la referencia del lenguaje.
Conversión mejorada de grupo de métodos a delegado
El estándar de C# en conversiones de grupo de métodos ahora incluye el siguiente elemento:
- La conversión se permite (pero no necesaria) para usar una instancia de delegado existente que ya contiene estas referencias.
Las versiones anteriores del estándar prohibían al compilador reutilizar el objeto delegado creado para una conversión de grupo de métodos. El compilador de C# 11 almacena en caché el objeto delegado creado a partir de una conversión de grupo de métodos y reutiliza ese objeto delegado único. Esta característica se incluyó por primera vez en Visual Studio 2022 versión 17.2 como característica en vista previa y en .NET 7 (versión preliminar 2).
Literales de cadena sin formato
Los literales de cadena sin formato son un nuevo formato para los literales de cadena. Los literales de cadena sin formato pueden contener texto arbitrario, como espacios en blanco, nuevas líneas, comillas insertadas y otros caracteres especiales sin necesidad de secuencias de escape. Un literal de cadena sin formato comienza con al menos tres caracteres de comillas dobles ("""). Y termina con el mismo número de caracteres de comillas dobles. Normalmente, un literal de cadena sin formato usa tres comillas dobles en una sola línea para iniciar la cadena y tres comillas dobles en una línea independiente para finalizar la cadena. Las nuevas líneas que siguen a la comilla de apertura y preceden a la comilla de cierre no se incluyen en el contenido final:
string longMessage = """
This is a long message.
It has several lines.
Some are indented
more than others.
Some should start at the first column.
Some have "quoted text" in them.
""";
Cualquier espacio en blanco a la izquierda de las comillas dobles de cierre se quitará del literal de cadena. Los literales de cadena sin formato se pueden combinar con la interpolación de cadenas para incluir llaves en el texto de salida. Varios caracteres $
indican cuántas llaves consecutivas comienzan y terminan la interpolación:
var location = $$"""
You are at {{{Longitude}}, {{Latitude}}}
""";
En el ejemplo anterior se especifica que dos llaves inician y finalizan una interpolación. La tercera llave de apertura y cierre repetida se incluye en la cadena de salida.
Puede encontrar más información sobre los literales de cadena sin formato en el artículo sobre cadenas de la guía de programación y los artículos de referencia del lenguaje sobre literales de cadena y cadenas interpoladas.
Estructuras predeterminadas automáticas
El compilador de C# 11 garantiza que todos los campos de un tipo struct
se inicializarán en su valor predeterminado como parte de la ejecución de un constructor. Este cambio significa que el compilador inicializa automáticamente cualquier campo o propiedad automática no inicializados por un constructor. Las estructuras en las que el constructor no asigna definitivamente todos los campos ahora se compilan, mientras que los campos que no se inicializan explícitamente se establecen en su valor predeterminado. Puede obtener más información sobre cómo afecta este cambio a la inicialización de estructuras en el artículo sobre estructuras.
Span<char>
de coincidencia de patrón o ReadOnlySpan<char>
en una constante string
Ha podido probar si un elemento string
tiene un valor constante específico mediante la coincidencia de patrones en varias versiones. Ahora, puede usar la misma lógica de coincidencia de patrones con variables que son Span<char>
o ReadOnlySpan<char>
.
Ámbito nameof ampliado
Los nombres de parámetro de tipo y los de parámetro ahora están en el ámbito cuando se usan en una expresión nameof
de una declaración de atributo del método. Esta característica significa que puede usar el operador nameof
para especificar el nombre de un parámetro de método en un atributo de una declaración de método o parámetro. Esta característica suele ser útil para agregar atributos y llevar a cabo análisis que admitan valores NULL.
Literales de cadena de UTF-8
Puede especificar el sufijo u8
en un literal de cadena para especificar la codificación de caracteres UTF-8. Si la aplicación necesita cadenas UTF-8, para constantes de cadena HTTP o protocolos de texto similares, puede usar esta característica para simplificar la creación de cadenas UTF-8.
Puede obtener más información sobre los literales de cadena UTF-8 en la sección literal de cadena del artículo sobre los tipos de referencia integrados.
Miembros requeridos
Puede agregar el modificadorrequired
a propiedades y campos para aplicar constructores y llamadores para inicializar esos valores. El System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute se puede agregar a constructores para informar al compilador de que un constructor inicializa todos los miembros necesarios.
Para obtener más información sobre los miembros necesarios, consulte la sección solo inicial del artículo de propiedades.
Campos ref
y variables ref scoped
Puede declarar campos ref
en ref struct
. Esto admite el uso de tipos como System.Span<T> sin atributos especiales o tipos internos ocultos.
Puede agregar el modificador scoped
a cualquier declaración de ref
. Esto limita el ámbito al que la referencia puede escapar.
Tipos locales de archivo
A partir de C# 11, el modificador de acceso file
se puede usar para crear un tipo cuya visibilidad esté limitada al archivo de origen en el que se declara. Esta característica ayuda a los autores de generadores de código fuente a evitar conflictos de nomenclatura. Puede obtener más información sobre esta característica en el artículo sobre tipos con ámbito de archivo en la sección de referencia del lenguaje.