次の方法で共有


.NET 8.0.100 から .NET 9.0.100 以降の Roslyn での破壊的変更

このドキュメントでは、.NET 8 一般リリース (.NET SDK バージョン 8.0.100) から .NET 9 一般リリース (.NET SDK バージョン 9.0.100) までの Roslyn での既知の破壊的変更を示します。

レコード構造体型の InlineArray 属性は許可されなくなりました。

Visual Studio 2022 バージョン 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)
{
}

C# 13 以降では、反復子によって安全なコンテキストが導入されます。

Visual Studio 2022 バージョン 17.11 で導入されました

言語仕様では、反復子が安全なコンテキストを導入すると述べていますが、Roslyn は C# 12 以前では実装しません。 これは、反復子の安全でないコードを できるようにする機能の一部として C# 13 で変更されます。 この変更により、反復子で安全でないコンストラクトを直接使用することが許可されていないため、通常のシナリオは中断されません。 ただし、以前に安全でないコンテキストがローカル関数として入れ子になって継承されたシナリオを破壊する可能性があります。例えば次の通りです:

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

unsafe 修飾子をローカル関数に追加するだけで、中断を回避できます。

C# 13 以降のオーバーロード解決に伴うコレクション式の重大な変更

C# 13 以降の を使用する場合に Visual Studio 2022 バージョン 17.12 以降で導入されました

C# 13 では、コレクション式のバインドにいくつかの変更があります。 大部分はあいまいさを解消して正常にコンパイルしますが、2 つの破壊的な変更があり、新しいコンパイルエラーを引き起こしたり、動作が変化する原因となります。 以下に詳しく説明します。

空のコレクション式では、API がオーバーロードのタイブレークとなるスパンであるかどうかを示す情報を使用しなくなりました。

オーバーロードされたメソッドに空のコレクション式が渡され、明確な要素型がない場合、ある API を優先するかどうかを決定するために、その API が ReadOnlySpan<T>Span<T> のどちらを受け取ったかという情報は使用されなくなりました。 次に例を示します。

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

正確な要素の型が他のすべてより優先されます。

C# 13 では、式からの変換を考慮し、正確に一致する要素型を優先します。 これにより、定数が関係する場合に動作が変化する可能性があります。

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

DefaultMemberAttribute の適切な宣言がない場合のインデクサーの宣言は許可されなくなりました。

Visual Studio 2022 バージョン 17.13 で導入

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

既定のパラメーターとパラメス パラメーターは、メソッド グループの標準型と見なされます。

Visual Studio 2022 バージョン 17.13 で導入

以前は、コンパイラ 推論されていました。 あいまいさのエラーが出力されるようになりました。

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

また、LangVersion=12 以下では、一意のデリゲート シグネチャを推論するには、params 修飾子がすべてのメソッドで一致する必要があります。 これはLangVersion=13のため、以降には影響しないことを注意してください。

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

回避策は、そのような場合に var 推論に依存するのではなく、明示的なデリゲート型を使用することです。

dotnet_style_require_accessibility_modifiers インターフェイス メンバーに一貫して適用されるようになりました

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

この変更の前に、dotnet_style_require_accessibility_modifiersの解析ツールはインターフェイスメンバーを無視していました。 これは、C# が最初にインターフェイス メンバーの修飾子を完全に禁止し、常にパブリックにするためです。

以降のバージョンの言語では、この制限が緩和され、ユーザーは、冗長な public 修飾子を含め、インターフェイス メンバーにアクセシビリティ修飾子を提供できます。

アナライザーが更新され、インターフェイス メンバーにもこのオプションの値が適用されるようになりました。 値の意味は次のとおりです。

  1. never。 アナライザーは分析を行いません。 冗長修飾子は、すべてのメンバーで使用できます。
  2. always。 冗長修飾子は、すべてのメンバー (インターフェイス メンバーを含む) で常に必要です。 たとえば、クラス メンバーの private 修飾子と、インターフェイス メンバーの public 修飾子などです。 これは、すべてのメンバーがどのような状況でも明示的にアクセシビリティを示す必要があると感じる場合に使用するオプションです。
  3. for_non_interface_members。 冗長な修飾子は、インターフェイスに含まれていないすべてのメンバーに必要ですが、インターフェイス メンバーには許可されません。 たとえば、プライベート クラス メンバーには private が必要です。 ただし、パブリック インターフェイス メンバーは、冗長な public 修飾子を持つことは許可されません。 これは、インターフェイス メンバーで修飾子を許可する言語の前に存在する標準的な修飾子アプローチと一致します。
  4. omit_if_default。 冗長修飾子は許可されません。 たとえば、プライベート クラス メンバーが privateを使用できないようにし、パブリック インターフェイス メンバーが publicを使用できないようにします。 これは、言語が既定で選択したものと一致したときにアクセシビリティを再記述することが冗長であり、禁止する必要があると感じる場合に使用するオプションです。