Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este documento se enumeran los cambios disruptivos conocidos en Roslyn después de la versión general de .NET 8 (versión 8.0.100 del SDK de .NET) hasta la versión general de .NET 9 (versión 9.0.100 del SDK de .NET).
Ya no se permite el atributo InlineArray en un tipo de estructura de registro.
Introducido en Visual Studio 2022, versión 17.11
[System.Runtime.CompilerServices.InlineArray(10)] // error CS9259: Attribute 'System.Runtime.CompilerServices.InlineArray' cannot be applied to a record struct.
record struct Buffer1()
{
private int _element0;
}
[System.Runtime.CompilerServices.InlineArray(10)] // error CS9259: Attribute 'System.Runtime.CompilerServices.InlineArray' cannot be applied to a record struct.
record struct Buffer2(int p1)
{
}
Los iteradores presentan contexto seguro en C# 13 y versiones más recientes
Introducido en Visual Studio 2022, versión 17.11
Aunque la especificación del lenguaje indica que los iteradores presentan un contexto seguro, Roslyn no implementa eso en C# 12 ni en versiones inferiores. Esto cambiará en C# 13 como parte de una característica que permite código no seguro en iteradores. El cambio no interrumpe los escenarios normales, ya que no se permite usar construcciones no seguras directamente en iteradores de todos modos. Sin embargo, puede interrumpir escenarios en los que un contexto no seguro se heredó previamente en funciones locales anidadas, como:
unsafe class C // unsafe context
{
System.Collections.Generic.IEnumerable<int> M() // an iterator
{
yield return 1;
local();
void local()
{
int* p = null; // allowed in C# 12; error in C# 13
}
}
}
Puede solucionar el salto simplemente agregando el modificador unsafe a la función local.
Cambios importantes en expresiones de colecciones con resolución de sobrecarga en C# 13 y versiones más recientes
Se introdujo en Visual Studio 2022, versión 17.12 y versiones posteriores al usar C# 13+
Hay algunos cambios en la vinculación de expresiones de colección en C# 13. La mayoría de estos resuelven ambigüedades para permitir que las compilaciones se realicen correctamente, pero algunos generan cambios importantes que dan lugar a un nuevo error de compilación o a un cambio importante en el comportamiento. A continuación se detallan.
Expresiones de colecciones vacías que ya no consideran si una API es un intervalo para resolver sobrecargas.
Cuando se proporciona una expresión de colección vacía a un método sobrecargado y no se especifica un tipo de elemento claro, ya no se decide utilizar una API basándose en si acepta ReadOnlySpan<T> o Span<T> para decidir si se debe preferir esa API. Por ejemplo:
class C
{
static void M(ReadOnlySpan<int> ros) {}
static void M(Span<object> s) {}
static void Main()
{
M([]); // C.M(ReadOnlySpan<int>) in C# 12, error in C# 13.
}
}
El tipo de elemento exacto se prefiere sobre todo lo demás
En C# 13, preferimos una coincidencia exacta del tipo de elemento, analizando las conversiones a partir de expresiones. Esto puede dar lugar a un cambio de comportamiento al implicar constantes:
class C
{
static void M1(ReadOnlySpan<byte> ros) {}
static void M1(Span<int> s) {}
static void M2(ReadOnlySpan<string> ros) {}
static void M2(Span<CustomInterpolatedStringHandler> ros) {}
static void Main()
{
M1([1]); // C.M(ReadOnlySpan<byte>) in C# 12, C.M(Span<int>) in C# 13
M2([$"{1}"]); // C.M(ReadOnlySpan<string>) in C# 12, C.M(Span<CustomInterpolatedStringHandler>) in C# 13
}
}
Ya no se permite la declaración de indizadores en ausencia de la declaración adecuada de DefaultMemberAttribute.
Introducido en Visual Studio 2022, versión 17.13
public interface I1
{
public I1 this[I1 args] { get; } // error CS0656: Missing compiler required member 'System.Reflection.DefaultMemberAttribute..ctor'
}
Los parámetros predeterminados y params se consideran en el tipo natural del grupo de métodos
Introducido en Visual Studio 2022, versión 17.13
Anteriormente, el compilador infirió inesperadamente un tipo de delegado diferente en función del orden de los candidatos en el origen cuando se usaran los valores de parámetro predeterminados o params matrices. Ahora se emite un error de ambigüedad.
using System;
class Program
{
static void Main()
{
var x1 = new Program().Test1; // previously Action<long[]> - now error
var x2 = new Program().Test2; // previously anonymous void delegate(params long[]) - now error
x1();
x2();
}
}
static class E
{
static public void Test1(this Program p, long[] a) => Console.Write(a.Length);
static public void Test1(this object p, params long[] a) => Console.Write(a.Length);
static public void Test2(this object p, params long[] a) => Console.Write(a.Length);
static public void Test2(this Program p, long[] a) => Console.Write(a.Length);
}
También en LangVersion=12 o inferior, el modificador params debe coincidir en todos los métodos para deducir una firma de delegado única.
Tenga en cuenta que esto no afecta a LangVersion=13 ni a las versiones posteriores debido a un algoritmo de inferencia de delegados diferente.
var d = new C().M; // previously inferred Action<int[]> - now error CS8917: the delegate type could not be inferred
static class E
{
public static void M(this C c, params int[] x) { }
}
class C
{
public void M(int[] x) { }
}
Una solución alternativa consiste en usar tipos de delegado explícitos en lugar de confiar en la inferencia de var en esos casos.
dotnet_style_require_accessibility_modifiers ahora se aplica de forma coherente a los miembros de la interfaz
PR: https://github.com/dotnet/roslyn/pull/76324
Antes de este cambio, el analizador de dotnet_style_require_accessibility_modifiers simplemente omitiría los miembros de la interfaz. Esto se debe a que C# inicialmente no permite modificadores para los miembros de la interfaz por completo, ya que siempre son públicos.
Las versiones posteriores del lenguaje relajaron esta restricción, lo que permite a los usuarios proporcionar modificadores de accesibilidad en los miembros de la interfaz, incluido un modificador redundante public .
El analizador se actualizó para aplicar ahora también el valor de esta opción en los miembros de la interfaz. El significado del valor es el siguiente:
-
never. El analizador no realiza ningún análisis. Se permiten modificadores redundantes en todos los miembros. -
always. Los modificadores redundantes siempre son necesarios en todos los miembros (incluidos los miembros de interfaz). Por ejemplo: un modificadorprivateen un miembro de clase y un modificadorpublicen un miembro de interfaz. Esta es la opción a utilizar si considera que todos los miembros, sin importar qué, deben indicar explícitamente su accesibilidad. -
for_non_interface_members. Los modificadores redundantes son necesarios en todos los miembros que no forman parte de una interfaz, pero no se permiten para los miembros de la interfaz. Por ejemplo, se requeriráprivateen los miembros de clase privada. Sin embargo, no se permitirá que un miembro de interfaz pública tenga modificadores redundantespublic. Esto coincide con el enfoque del modificador estándar presente antes de que el lenguaje permitiera modificadores en los miembros de la interfaz. -
omit_if_default. No se permiten modificadores redundantes. Por ejemplo, un miembro de clase privada no podrá usarprivatey no se permitirá a un miembro de interfaz pública usarpublic. Esta es la opción que se debe usar si considera que volver a indicar la accesibilidad cuando coincide con lo que elige el idioma de forma predeterminada es redundante y no se debe permitir.
Roslyn breaking changes