Bagikan melalui


Perubahan signifikan dalam Roslyn setelah .NET 7.0.100 hingga .NET 8.0.100

Dokumen ini mencantumkan perubahan mencolok yang diketahui di Roslyn setelah rilis umum .NET 7 (.NET SDK versi 7.0.100) melalui rilis umum .NET 8 (.NET SDK versi 8.0.100).

Pengubah ref argumen dinamis harus kompatibel dengan pengubah ref dari parameter yang sesuai

Diperkenalkan di Visual Studio 2022 versi 17.10

Pengubah ref argumen dinamis harus kompatibel dengan pengubah ref parameter yang sesuai pada waktu kompilasi. Ini dapat menyebabkan penyelesaian kelebihan beban yang melibatkan argumen dinamis gagal pada waktu kompilasi daripada waktu berjalan.

Sebelumnya, ketidakcocokan diizinkan pada waktu kompilasi, menunda kegagalan resolusi kelebihan beban ke runtime.

Misalnya, kode berikut sebelumnya dapat dikompilasi tanpa kesalahan, tetapi mengalami kegagalan dengan pengecualian: "Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Metode overload terbaik yang cocok untuk 'C.f(ref object)' memiliki beberapa argumen yang tidak valid" Sekarang, kode ini akan menghasilkan kesalahan kompilasi.

public class C
{
    public void f(ref dynamic a) 
    {
    }
    
    public void M(dynamic d)
    {
        f(d); // error CS1620: Argument 1 must be passed with the 'ref' keyword
    }
}

Ekspresi koleksi untuk tipe IEnumerable yang diimplementasikan harus memiliki elemen yang dapat dikonversi secara implisit ke object

Diperkenalkan di Visual Studio 2022 versi 17.10

Konversi ekspresi koleksi ke struct atau class yang mengimplementasikan System.Collections.IEnumerable dan tidak memiliki tipe yang kuat mengharuskan GetEnumerator() elemen dalam ekspresi koleksi secara implisit dapat dikonversi ke object. Sebelumnya, elemen ekspresi koleksi yang menargetkan implementasi IEnumerable diasumsikan dapat dikonversi ke object, dan dikonversi hanya saat terhubung ke metode Add yang berlaku.

Persyaratan tambahan ini berarti bahwa konversi ekspresi pengumpulan ke IEnumerable implementasi diperlakukan secara konsisten dengan jenis target lain di mana elemen dalam ekspresi koleksi harus secara implisit dapat dikonversi ke jenis perulangan dari jenis target.

Perubahan ini memengaruhi ekspresi koleksi yang menargetkan implementasi IEnumerable di mana elemen mengandalkan pengetikan target ke jenis parameter metode yang bertipe kuat Add. Dalam contoh di bawah ini, kesalahan dilaporkan yang _ => { } tidak dapat dikonversi secara implisit ke object.

class Actions : IEnumerable
{
    public void Add(Action<int> action);
    // ...
}

Actions a = [_ => { }]; // error CS8917: The delegate type could not be inferred.

Untuk mengatasi kesalahan, ekspresi elemen dapat ditik secara eksplisit.

a = [(int _) => { }];          // ok
a = [(Action<int>)(_ => { })]; // ok

Jenis target ekspresi kumpulan harus memiliki konstruktor dan metode Add.

Diperkenalkan di Visual Studio 2022 versi 17.10

Konversi ekspresi koleksi ke struct atau class yang mengimplementasikan System.Collections.IEnumerable dan tidak memiliki CollectionBuilderAttribute memerlukan jenis target untuk memiliki konstruktor yang dapat diakses yang dapat dipanggil tanpa argumen dan, jika ekspresi koleksi tidak kosong, jenis target harus memiliki metode yang dapat diakses Add yang dapat dipanggil dengan argumen tunggal.

Sebelumnya, konstruktor dan Add metode diperlukan untuk pembuatan instans himpunan, tetapi tidak untuk konversi. Itu berarti panggilan berikut bersifat ambigu karena ekspresi koleksi dapat memiliki baik char[] maupun string sebagai jenis target yang valid. Panggilan tidak lagi ambigu karena string tidak memiliki konstruktor atau Add metode tanpa parameter.

Print(['a', 'b', 'c']); // calls Print(char[])

static void Print(char[] arg) { }
static void Print(string arg) { }

ref argumen dapat diteruskan ke in parameter

Diperkenalkan pada Visual Studio 2022 versi 17.8p2

Parameter fitur ref readonly melonggarkan resolusi kelebihan beban yang memungkinkan ref argumen diteruskan ke in parameter saat LangVersion diatur ke 12 atau yang lebih baru. Ini dapat menyebabkan perubahan perilaku atau pemecahan sumber:

var i = 5;
System.Console.Write(new C().M(ref i)); // prints "E" in C# 11, but "C" in C# 12
System.Console.Write(E.M(new C(), ref i)); // workaround: prints "E" always

class C
{
    public string M(in int i) => "C";
}
static class E
{
    public static string M(this C c, ref int i) => "E";
}
var i = 5;
System.Console.Write(C.M(null, ref i)); // prints "1" in C# 11, but fails with an ambiguity error in C# 12
System.Console.Write(C.M((I1)null, ref i)); // workaround: prints "1" always

interface I1 { }
interface I2 { }
static class C
{
    public static string M(I1 o, ref int x) => "1";
    public static string M(I2 o, in int x) => "2";
}

Lebih mengutamakan pembuangan berbasis pola daripada berbasis antarmuka dalam operasi asinkron using

Diperkenalkan di Visual Studio 2022 versi 17.10p3

Asinkron using lebih suka mengikat menggunakan metode berbasis pola DisposeAsync() daripada berbasis antarmuka IAsyncDisposable.DisposeAsync().

Misalnya, metode publik DisposeAsync() akan dipilih, bukan implementasi antarmuka privat:

await using (var x = new C()) { }

public class C : System.IAsyncDisposable
{
    ValueTask IAsyncDisposable.DisposeAsync() => throw null; // no longer picked

    public async ValueTask DisposeAsync()
    {
        Console.WriteLine("PICKED");
        await Task.Yield();
    }
}