Bagikan melalui


Gelombang peringatan C#

Peringatan dan kesalahan baru dapat ditemukan di setiap rilis pengompilasi C#. Saat peringatan baru dapat dilaporkan pada kode yang ada, peringatan tersebut ditemukan di bawah sistem keikutsertaan yang disebut sebagai gelombang peringatan. Sistem keikutsertaan berarti Anda tidak akan melihat peringatan baru pada kode yang ada tanpa perlu melakukan tindakan untuk mengaktifkannya. Gelombang peringatan diaktifkan dengan menggunakan elemen AnalysisLevel dalam file proyek Anda. Ketika <TreatWarningsAsErrors>true</TreatWarningsAsErrors> ditentukan, peringatan gelombang peringatan yang diaktifkan akan menghasilkan kesalahan. Diagnostik gelombang peringatan 5 ditambahkan dalam C# 9. Diagnostik gelombang peringatan 6 ditambahkan dalam C# 10. Diagnostik gelombang peringatan 7 ditambahkan dalam C# 11. Diagnostik gelombang peringatan 8 ditambahkan di C# 12.

CS9123 - Mengambil alamat lokal atau parameter dalam metode asinkron dapat membuat lubang GC.

Peringatan gelombang 8

Operator & tidak boleh digunakan pada parameter atau variabel lokal dalam metode asinkron. Kode berikut menghasilkan CS9123:

public static async Task LogValue()
{
    int x = 1;
    unsafe {
        int* y = &x;
        Console.WriteLine(*y);
    }
    await Task.Delay(1000);
}

CS8981 - Nama jenis hanya berisi karakter ascii dengan huruf kecil.

Gelombang peringatan 7

Setiap kata kunci baru yang ditambahkan untuk C# akan berupa karakter ASCII dengan huruf kecil. Peringatan ini memastikan bahwa tidak ada jenis Anda yang bertentangan dengan kata kunci yang ada di masa mendatang. Kode berikut menghasilkan CS8981:

public class lowercasename
{
}

Anda dapat menangani peringatan ini dengan mengganti nama jenis untuk menyertakan setidaknya satu karakter ASCII dengan huruf kecil, seperti karakter huruf besar, digit, atau garis bawah.

CS8826 - Deklarasi metode parsial memiliki perbedaan tanda tangan.

Gelombang peringatan 6

Peringatan ini memperbaiki beberapa inkonsistensi dalam melaporkan perbedaan antar-tanda tangan metode parsial. Pengompilasi akan selalu melaporkan kesalahan ketika tanda tangan metode parsial membuat tanda tangan CLR yang berbeda. Sekarang, pengompilasi melaporkan CS8826 saat tanda tangan secara sintaksis berbeda C#. Pertimbangkan kelas parsial berikut:

public partial class PartialType
{
    public partial void M1(int x);

    public partial T M2<T>(string s) where T : struct;

    public partial void M3(string s);


    public partial void M4(object o);
    public partial void M5(dynamic o);
    public partial void M6(string? s);
}

Implementasi kelas parsial berikut menghasilkan beberapa contoh CS8626:

public partial class PartialType
{
    // Different parameter names:
    public partial void M1(int y) { }

    // Different type parameter names:
    public partial TResult M2<TResult>(string s) where TResult : struct => default;

    // Relaxed nullability
    public partial void M3(string? s) { }


    // Mixing object and dynamic
    public partial void M4(dynamic o) { }

    // Mixing object and dynamic
    public partial void M5(object o) { }

    // Note: This generates CS8611 (nullability mismatch) not CS8826
    public partial void M6(string s) { }
}

Catatan

Jika implementasi metode menggunakan jenis referensi yang tidak dapat diubah ke null saat deklarasi lain menerima jenis referensi yang dapat diubah ke null, CS8611 akan dihasilkan, alih-alih CS8826.

Untuk memperbaiki instans peringatan ini, pastikan kedua tanda tangan cocok.

CS7023 - Jenis statik digunakan dalam ekspresi 'is' atau 'as'.

Gelombang peringatan 5

Ekspresi is dan as selalu mengembalikan false untuk jenis statik karena Anda tidak dapat membuat instans jenis statik. Kode berikut menghasilkan CS7023:

static class StaticClass
{
    public static void Thing() { }
}

void M(object o)
{
    // warning: cannot use a static type in 'is' or 'as'
    if (o is StaticClass)
    {
        Console.WriteLine("Can't happen");
    }
    else
    {
        Console.WriteLine("o is not an instance of a static class");
    }
}

Pengompilasi melaporkan peringatan ini karena pengujian jenis tidak pernah berhasil. Untuk memperbaiki peringatan ini, hapus pengujian dan hapus kode yang dijalankan hanya jika pengujian berhasil. Dalam contoh sebelumnya, klausul else selalu dijalankan. Isi metode dapat digantikan oleh baris tunggal tersebut:

Console.WriteLine("o is not an instance of a static class");

CS8073 - Hasil ekspresi selalu 'false' (atau 'true').

Gelombang peringatan 5

Operator == dan != selalu mengembalikan false (atau true) saat membandingkan instans jenis struct dengan null. Kode berikut menunjukkan peringatan ini. Asumsikan S adalah struct yang telah menentukan operator == dan operator !=:

class Program
{
    public static void M(S s)
    {
        if (s == null) { } // CS8073: The result of the expression is always 'false'
        if (s != null) { } // CS8073: The result of the expression is always 'true'
    }
}

struct S
{
    public static bool operator ==(S s1, S s2) => s1.Equals(s2);
    public static bool operator !=(S s1, S s2) => !s1.Equals(s2);
    public override bool Equals(object? other)
    {
        // Implementation elided
        return false;
    }
    public override int GetHashCode() => 0;

    // Other details elided...
}

Untuk memperbaiki kesalahan ini, hapus pemeriksaan null dan kode yang akan dijalankan jika objeknya adalah null.

CS8848 - Operator 'from' tidak dapat digunakan di sini karena alasan prioritas. Gunakan tanda kurung untuk membedakan.

Gelombang peringatan 5

Contoh berikut menunjukkan peringatan ini. Ekspresi salah mengikat karena prioritas operator.

bool b = true;
var source = new Src();
b = true;
source = new Src();
var a = b && from c in source select c;
Console.WriteLine(a);

var indexes = new Src2();
int[] array = { 1, 2, 3, 4, 5, 6, 7 };
var range = array[0..from c in indexes select c];

Untuk memperbaiki kesalahan ini, letakkan tanda kurung di sekitar ekspresi kueri:

bool b = true;
var source = new Src();
b = true;
source = new Src();
var a = b && (from c in source select c);
Console.WriteLine(a);

var indexes = new Src2();
int[] array = { 1, 2, 3, 4, 5, 6, 7 };
var range = array[0..(from c in indexes select c)];

Anggota harus sepenuhnya ditetapkan, penggunaan variabel yang tidak ditetapkan (CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS8886, CS8887)

Gelombang peringatan 5

Beberapa peringatan meningkatkan analisis penugasan pasti untuk jenis struct yang dideklarasikan dalam rakitan yang diimpor. Semua peringatan baru ini dihasilkan ketika struktur dalam rakitan yang diimpor mencakup bidang yang tidak dapat diakses (biasanya bidang private) dari jenis referensi, seperti yang ditunjukkan dalam contoh berikut:

public struct Struct
{
    private string data = String.Empty;
    public Struct() { }
}

Contoh berikut menunjukkan peringatan yang dihasilkan dari peningkatan analisis penugasan pasti:

  • CS8880: Properti 'Property' yang diimplementasikan secara otomatis harus sepenuhnya ditetapkan sebelum kontrol dikembalikan ke pemanggil.
  • CS8881: Bidang 'field' harus sepenuhnya ditetapkan sebelum kontrol dikembalikan ke pemanggil.
  • CS8882: Parameter keluar 'parameter' harus ditetapkan sebelum kontrol meninggalkan metode saat ini.
  • CS8883: Penggunaan properti 'Property' yang diimplementasikan secara otomatis yang mungkin tidak ditetapkan.
  • CS8884: Penggunaan bidang 'Field' yang mungkin tidak ditetapkan
  • CS8885: Objek 'this' tidak dapat digunakan sebelum semua bidangnya ditetapkan.
  • CS8886: Penggunaan parameter output 'parameterName' yang tidak ditetapkan.
  • CS8887: Penggunaan variabel lokal 'variableName' yang tidak ditetapkan
public struct DefiniteAssignmentWarnings
{
    // CS8880
    public Struct Property { get; }
    // CS8881
    private Struct field;

    // CS8882
    public void Method(out Struct s)
    {

    }

    public DefiniteAssignmentWarnings(int dummy)
    {
        // CS8883
        Struct v2 = Property;
        // CS8884
        Struct v3 = field;
        // CS8885:
        DefiniteAssignmentWarnings p2 = this;
    }

    public static void Method2(out Struct s1)
    {
        // CS8886
        var s2 = s1;
        s1 = default;
    }

    public static void UseLocalStruct()
    {
        Struct r1;
        var r2 = r1;
    }
}

Anda dapat memperbaiki salah satu peringatan ini dengan menginisialisasi atau menetapkan struktur yang diimpor ke nilai defaultnya:

public struct DefiniteAssignmentNoWarnings
{
    // CS8880
    public Struct Property { get; } = default;
    // CS8881
    private Struct field = default;

    // CS8882
    public void Method(out Struct s)
    {
        s = default;
    }

    public DefiniteAssignmentNoWarnings(int dummy)
    {
        // CS8883
        Struct v2 = Property;
        // CS8884
        Struct v3 = field;
        // CS8885:
        DefiniteAssignmentNoWarnings p2 = this;
    }

    public static void Method2(out Struct s1)
    {
        // CS8886
        s1 = default;
        var s2 = s1;
    }

    public static void UseLocalStruct()
    {
        Struct r1 = default;
        var r2 = r1;
    }
}

CS8892 - Metode tidak akan digunakan sebagai titik entri karena titik entri sinkron 'method' ditemukan.

Gelombang peringatan 5

Peringatan ini dihasilkan pada semua kandidat titik entri asinkron saat Anda memiliki beberapa titik entri yang valid, termasuk satu atau beberapa titik entri sinkron.

Contoh berikut menghasilkan CS8892:

public static void Main()
{
    RunProgram();
}

// CS8892
public static async Task Main(string[] args)
{
    await RunProgramAsync();
}

Catatan

Pengompilasi selalu menggunakan titik entri sinkron. Jika ada beberapa titik entri sinkron, Anda akan mendapatkan kesalahan pengompilasi.

Untuk memperbaiki peringatan ini, hapus atau ganti nama titik entri asinkron.

CS8897 - jenis statik tidak dapat digunakan sebagai parameter

Gelombang peringatan 5

Anggota antarmuka tidak dapat mendeklarasikan parameter yang jenisnya adalah kelas statik. Kode berikut menunjukkan CS8897 dan CS8898:

public static class Utilities
{
    // elided
}

public interface IUtility
{
    // CS8897
    public void SetUtility(Utilities u);

    // CS8898
    public Utilities GetUtility();
}

Untuk memperbaiki peringatan ini, ubah jenis parameter atau hapus metodenya.

CS8898 - jenis statik tidak dapat digunakan sebagai jenis pengembalian

Gelombang peringatan 5

Anggota antarmuka tidak dapat mendeklarasikan jenis pengembalian yang merupakan kelas statik. Kode berikut menunjukkan CS8897 dan CS8898:

public static class Utilities
{
    // elided
}

public interface IUtility
{
    // CS8897
    public void SetUtility(Utilities u);

    // CS8898
    public Utilities GetUtility();
}

Untuk memperbaiki peringatan ini, ubah jenis pengembalian atau hapus metodenya.