Modifications majeures dans Roslyn de .NET 8.0.100 à .NET 9.0.100

Ce document répertorie les modifications disruptives connues dans Roslyn de la version générale du .NET 8 (version 8.0.100 du SDK .NET) à la version générale du .NET 9 (version 9.0.100 du SDK .NET).

L’attribut InlineArray sur une structure de type record n’est plus autorisé.

Introduit dans Visual Studio 2022 version 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)
{
}

Les itérateurs introduisent un contexte sécurisé en C# 13 et versions ultérieures

Introduit dans Visual Studio 2022 version 17.11

Bien que la spécification du langage indique que les itérateurs introduisent un contexte sûr, Roslyn n’implémente pas cela en C# 12 et inférieur. Cela va changer en C# 13 dans le cadre d’une fonctionnalité qui autorise le code non sécurisé dans les itérateurs. Le changement n’interrompt pas les scénarios normaux, car il n’était pas autorisé à utiliser des constructions non sécurisées directement dans les itérateurs de toute façon. Toutefois, il peut interrompre les scénarios où un contexte non sécurisé a été précédemment hérité dans des fonctions locales imbriquées, par exemple :

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
        }
    }
}

Vous pouvez contourner ce changement simplement en ajoutant le modificateur unsafe à la fonction locale.

Changements majeurs de l’expression de collection avec la résolution de surcharge dans C# 13 et les versions ultérieures

Introduit dans Visual Studio 2022 version 17.12 et ultérieure lors de l’utilisation de C# 13+

Il y a quelques modifications dans la liaison d'expressions de collections en C# 13. La plupart d'entre eux transforment des ambiguïtés en compilations réussies, mais quelques modifications de rupture entraînent soit une nouvelle erreur de compilation, soit constituent un changement de comportement disruptif. Elles sont détaillées ci-dessous.

Les expressions de collection vides ne varient plus selon que l’API est étendue au départage en cas de surcharge

Lorsqu'une expression de collection vide est fournie à une méthode surchargée et qu'aucun type d'élément clair n'est défini, nous ne nous basons plus sur si une API utilise ReadOnlySpan<T> ou Span<T> pour déterminer si cette API doit être privilégiée. Par exemple:

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.
    }
}

Le type d’élément exact est préféré à tous les autres

En C# 13, nous préférons une correspondance exacte du type de l'élément, en analysant les conversions des expressions. Cela peut entraîner un changement de comportement lors de l’implication de 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
    }
}

La déclaration d’indexeurs en l’absence de déclaration appropriée de DefaultMemberAttribute n’est plus autorisée.

Introduit dans Visual Studio 2022 version 17.13

public interface I1
{
    public I1 this[I1 args] { get; } // error CS0656: Missing compiler required member 'System.Reflection.DefaultMemberAttribute..ctor'
}

Les paramètres `default` et `params` sont pris en compte dans le type naturel du groupe de méthodes.

Introduit dans Visual Studio 2022 version 17.13

Auparavant, le compilateur a déduit de manière inattendue différents types de délégués en fonction de l’ordre des candidats dans la source lorsque les valeurs de paramètre ou params les tableaux par défaut ont été utilisés. Une erreur d’ambiguïté est maintenant émise.

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);
}

En outre, dans LangVersion=12 ou inférieur, le modificateur params doit être le même dans toutes les méthodes pour inférer une signature de délégué unique. Notez que cela n'affecte pas LangVersion=13 ni ceux qui suivent, en raison d'un autre algorithme d'inférence de délégué.

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) { }
}

Une solution de contournement consiste à utiliser des types délégués explicites au lieu de s’appuyer sur l’inférence pour ces cas.

dotnet_style_require_accessibility_modifiers s’applique désormais de manière cohérente aux membres de l’interface

PR : https://github.com/dotnet/roslyn/pull/76324

Avant ce changement, l’analyseur pour dotnet_style_require_accessibility_modifiers ignorait simplement les membres de l’interface. Cela était dû au fait que C# avait initialement interdit les modificateurs pour les membres de l’interface, qui devaient toujours être publics.

Les versions ultérieures de la langue ont assoupli cette restriction, ce qui permet aux utilisateurs de fournir des modificateurs d’accessibilité sur les membres de l’interface, y compris un modificateur redondant public .

L’analyseur a été mis à jour pour appliquer désormais la valeur de cette option sur les membres de l’interface. La signification de la valeur est la suivante :

  1. never. L’analyseur n’effectue aucune analyse. Les modificateurs redondants sont autorisés sur tous les membres.
  2. always. Les modificateurs redondants sont toujours requis sur tous les membres (y compris les membres de l’interface). Par exemple : un modificateur private sur un membre de classe, et un modificateur public sur un membre d’interface. Il s’agit de l’option à utiliser si vous pensez que tous les membres, quel que soit ce qui doit indiquer explicitement leur accessibilité.
  3. for_non_interface_members. Les modificateurs redondants sont requis sur tous les membres qui ne font pas partie d’une interface, mais non autorisés pour les membres de l’interface. Par exemple : private est nécessaire sur les membres de classe privée. Toutefois, un membre d’interface publique n’est pas autorisé à avoir des modificateurs redondants public . Cela correspond à l’approche standard des modificateurs présente avant que le langage ne permette d'utiliser des modificateurs sur les membres des interfaces.
  4. omit_if_default. Les modificateurs redondants ne sont pas autorisés. Par exemple, un membre de classe privée n’est pas autorisé à utiliser privateet un membre d’interface publique n’est pas autorisé à utiliser public. Il s'agit de l'option à adopter si vous estimez que rappeler l'accessibilité lorsque celle-ci est définie selon les choix par défaut de la langue est superflu et devrait être évité.