Sdílet prostřednictvím


Zásadní změny v Roslynu po .NET 8.0.100 až .NET 9.0.100

Tento dokument uvádí známé zásadní změny v roslynu po obecné verzi .NET 8 (.NET SDK verze 8.0.100) až po obecnou verzi .NET 9 (.NET SDK verze 9.0.100).

Atribut InlineArray pro typ struktury záznamu již není povolen.

Představeno ve Visual Studio 2022 verze 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)
{
}

Iterátory představují bezpečný kontext v jazyce C# 13 a novějším

Představeno ve Visual Studio 2022 verze 17.11

Přestože specifikace jazyka uvádí, že iterátory představují bezpečný kontext, Roslyn to v C# 12 a nižších verzích neimplementuje. To se změní v jazyce C# 13 jako součást funkce , která umožňuje nezabezpečený kód v iterátorech. Změna neruší normální scénáře, protože bylo zakázáno používat nebezpečné konstruktory přímo v iterátorech. Může však narušit scénáře, kdy se dříve nebezpečný kontext zdědil do vnořených místních funkcí, například:

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

Konec můžete obejít jednoduše tak, že do místní funkce přidáte modifikátor unsafe.

Zásadní změny ve výrazech kolekce spojené s řešením přetížení v C# 13 a novějších

Představeno v sadě Visual Studio 2022 verze 17.12 a novější při použití jazyka C# 13 a novější

V vazbě výrazů kolekce v jazyce C# 13 došlo k několika změnám. Většina z nich převádí nejasnosti na úspěšné kompilace, ale pár z nich vede ke změnám, které buď způsobí nový kompilace chybu, nebo změnu chování. Jsou podrobně popsány níže.

Prázdné výrazy kolekce už nepoužívají API jako rozhodovací kritérium pro přetížení.

Pokud je pro přetíženou metodu zadán prázdný výraz kolekce a neexistuje jasný typ elementu, už nepoužíváme, jestli rozhraní API přebírá ReadOnlySpan<T>, nebo Span<T>, abychom se rozhodli, jestli má toto rozhraní API preferovat. Například:

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

Přesný typ prvku je upřednostňovaný před všemi ostatními

Ve verzi C# 13 dáváme přednost přesné shodě typu prvku s ohledem na převody z výrazů. Výsledkem může být změna chování při zapojení konstant:

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

Deklarace indexerů bez správné deklarace DefaultMemberAttribute už není povolená.

Představeno ve Visual Studio 2022 verze 17.13

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

Výchozí a parametry params jsou považovány za přirozený typ skupiny metod.

Představeno ve Visual Studio 2022 verze 17.13

Dříve kompilátor neočekávaně odvodil jiný typ delegáta v závislosti na pořadí kandidátů ve zdrojovém kódu, když byly použity výchozí hodnoty parametrů nebo pole params. Teď se vyhlásí chybová zpráva o nejednoznačnosti.

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

Také při LangVersion=12 nebo nižších musí modifikátor params být konzistentní napříč všemi metodami, aby se odvodil jedinečný podpis delegáta. Mějte na paměti, že to nemá vliv na LangVersion=13 a následující, protože algoritmus odvození delegátů je odlišný.

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

Alternativním řešením je použít explicitní typy delegátů místo toho, abyste se v těchto případech museli spoléhat na var odvozování.

dotnet_style_require_accessibility_modifiers se teď konzistentně vztahuje na členy rozhraní.

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

Před touto změnou by analyzátor pro dotnet_style_require_accessibility_modifiers jednoduše ignoroval členy rozhraní. Důvodem bylo to, že jazyk C# zpočátku nepovolil modifikátory pro členy rozhraní, přičemž vždy byly veřejné.

Novější verze jazyka toto omezení uvolnily, což uživatelům umožňuje poskytovat modifikátory přístupnosti u členů rozhraní, včetně redundantního modifikátoru public.

Analyzátor byl aktualizován tak, aby nyní vynucoval hodnotu této možnosti také u členů rozhraní. Význam hodnoty je následující:

  1. never. Analyzátor neprovádí žádnou analýzu. U všech členů jsou povoleny redundantní modifikátory.
  2. always. Redundantní modifikátory jsou vždy vyžadovány u všech členů (včetně členů rozhraní). Příklad: modifikátor private u členu třídy a modifikátor public členu rozhraní. To je možnost, kterou zvolíte, pokud máte pocit, že všichni členové bez ohledu na cokoli by měli výslovně uvést svou přístupnost.
  3. for_non_interface_members. Redundantní modifikátory jsou vyžadovány u všech členů , které nejsou součástí rozhraní, ale jsou zakázány pro členy rozhraní. Například: private bude vyžadováno u členů privátní třídy. Člen veřejného rozhraní ale nebude moct mít redundantní modifikátory public. Toto odpovídá standardnímu přístupu k modifikátorům, který byl přítomen před tím, než jazyk umožnil modifikátory na členech rozhraní.
  4. omit_if_default. Redundantní modifikátory jsou zakázány. Například soukromý člen třídy bude zakázáno používat privatea člen veřejného rozhraní bude zakázáno používat public. To je možnost, kterou byste měli použít, pokud považujete za to, že opakování přístupnosti, když odpovídá výchozímu nastavení jazyka, je nadbytečné a nemělo by být povoleno.