C#-varningsvågor

Nya varningar och fel kan introduceras i varje version av C#-kompilatorn. När nya varningar kan rapporteras om befintlig kod introduceras dessa varningar i ett opt-in-system som kallas för en varningsvåg. Opt-in-systemet innebär att du inte bör se nya varningar om befintlig kod utan att vidta åtgärder för att aktivera dem. Varningsvågor aktiveras med analysislevel-elementet i projektfilen. När <TreatWarningsAsErrors>true</TreatWarningsAsErrors> har angetts genererar aktiverade varningsvågor fel. Varningsvåg 5-diagnostik lades till i C# 9. Varningsvåg 6-diagnostik lades till i C# 10. Diagnostik för varningsvåg 7 lades till i C# 11. Varningsvåg 8-diagnostik lades till i C# 12.

CS9123 – Om du tar adressen till lokal eller parameter i asynkron metod kan du skapa ett GC-hål.

Varningsvåg 8

Operatorn & ska inte användas på parametrar eller lokala variabler i asynkrona metoder. Följande kod genererar CS9123:

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

CS8981 – Typnamnet innehåller endast gemener ascii-tecken.

Varningsvåg 7

Alla nya nyckelord som läggs till för C# är alla gemena ASCII-tecken. Den här varningen säkerställer att ingen av dina typer är i konflikt med framtida nyckelord. Följande kod genererar CS8981:

public class lowercasename
{
}

Du kan åtgärda den här varningen genom att byta namn på typen så att den innehåller minst ett ASCII-tecken som inte är gemener, till exempel versaler, siffror eller understreck.

CS8826 – Partiella metoddeklarationer har signaturskillnader.

Varningsvåg 6

Den här varningen korrigerar vissa inkonsekvenser i rapporteringsskillnader mellan partiella metodsignaturer. Kompilatorn rapporterade alltid ett fel när de partiella metodsignaturerna skapade olika CLR-signaturer. Nu rapporterar kompilatorn CS8826 när signaturerna är syntaktiskt olika C#. Överväg följande partiella klass:

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

Följande partiella klassimplementering genererar flera exempel på 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) { }
}

Kommentar

Om implementeringen av en metod använder en icke-nullbar referenstyp när den andra deklarationen accepterar null-referenstyper genereras CS8611 i stället för CS8826.

Om du vill åtgärda alla instanser av dessa varningar kontrollerar du att de två signaturerna matchar.

CS7023 – En statisk typ används i ett "is" eller "as"-uttryck.

Varningsvåg 5

Uttrycken is och as returnerar false alltid för en statisk typ eftersom du inte kan skapa instanser av en statisk typ. Följande kod genererar 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");
    }
}

Kompilatorn rapporterar den här varningen eftersom typtestet aldrig kan lyckas. Åtgärda varningen genom att ta bort testet och ta bort all kod som körs endast om testet lyckades. I föregående exempel else körs satsen alltid. Metodtexten kan ersättas med den enda raden:

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

CS8073 – Resultatet av uttrycket är alltid "falskt" (eller "sant").

Varningsvåg 5

Operatorerna == och returnerar false alltid (eller true) när en instans av en typ jämförs struct med null!= . Följande kod visar den här varningen. Anta S att är en struct som har definierat operator == och 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...
}

Åtgärda det här felet genom att ta bort null-kontrollen och koden som skulle köras om objektet är null.

CS8848 – Operatorn "från" kan inte användas här på grund av prioritet. Använd parenteser för att skilja sig åt.

Varningsvåg 5

Följande exempel visar den här varningen. Uttrycket binder felaktigt på grund av operatorernas prioritet.

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];

Åtgärda det här felet genom att placera parenteser runt frågeuttrycket:

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

Medlemmar måste vara helt tilldelade, användning av otilldelade variabler (CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS8886, CS8887)

Varningsvåg 5

Flera varningar förbättrar den definitiva tilldelningsanalysen för struct typer som deklarerats i importerade sammansättningar. Alla dessa nya varningar genereras när en struct i en importerad sammansättning innehåller ett otillgängligt fält (vanligtvis ett private fält) av en referenstyp, som visas i följande exempel:

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

Följande exempel visar varningarna som genereras från den förbättrade definitiva tilldelningsanalysen:

  • CS8880: Den automatiskt implementerade egenskapen "Property" måste tilldelas helt innan kontrollen returneras till anroparen.
  • CS8881: Fältet fält måste tilldelas fullständigt innan kontrollen returneras till anroparen.
  • CS8882: Out-parametern "parameter" måste tilldelas till innan kontrollen lämnar den aktuella metoden.
  • CS8883: Användning av den eventuellt otilldelade automatiskt implementerade egenskapen "Property".
  • CS8884: Användning av eventuellt otilldelade fält "Fält"
  • CS8885: Det här objektet kan inte användas innan alla dess fält har tilldelats.
  • CS8886: Användning av den otilldelade utdataparametern "parameterName".
  • CS8887: Användning av den otilldelade lokala variabeln "variableName"
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;
    }
}

Du kan åtgärda någon av dessa varningar genom att initiera eller tilldela den importerade structen till standardvärdet:

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 – Metoden används inte som startpunkt eftersom en synkron startpunkt för metoden hittades.

Varningsvåg 5

Den här varningen genereras på alla asynkrona startpunktskandidater när du har flera giltiga startpunkter, inklusive en eller flera synkrona startpunkter.

I följande exempel genereras CS8892:

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

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

Kommentar

Kompilatorn använder alltid den synkrona startpunkten. Om det finns flera synkrona startpunkter får du ett kompilatorfel.

Åtgärda varningen genom att ta bort eller byta namn på den asynkrona startpunkten.

CS8897 – Statiska typer kan inte användas som parametrar

Varningsvåg 5

Medlemmar i ett gränssnitt kan inte deklarera parametrar vars typ är en statisk klass. Följande kod visar både CS8897 och CS8898:

public static class Utilities
{
    // elided
}

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

    // CS8898
    public Utilities GetUtility();
}

Åtgärda varningen genom att ändra parametertypen eller ta bort metoden.

CS8898 – statiska typer kan inte användas som returtyper

Varningsvåg 5

Medlemmar i ett gränssnitt kan inte deklarera en returtyp som är en statisk klass. Följande kod visar både CS8897 och CS8898:

public static class Utilities
{
    // elided
}

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

    // CS8898
    public Utilities GetUtility();
}

Åtgärda varningen genom att ändra returtypen eller ta bort metoden.