C#-Warnungswellen

In jeder Version des C#-Compilers können neue Warnungen und Fehler eingeführt werden. Wenn neue Warnungen im vorhandenen Code gemeldet werden können, werden diese Warnungen unter einem Opt-In-System eingeführt, das als Warnwelle bezeichnet wird. Das Opt-In-System bedeutet, dass neue Warnungen für vorhandenen Code nicht angezeigt werden sollten, ohne Maßnahmen zu ergreifen, um sie zu aktivieren. Warnungswellen werden mithilfe des AnalysisLevel-Elements in Ihrer Projektdatei aktiviert. Wenn <TreatWarningsAsErrors>true</TreatWarningsAsErrors> angegeben wird, generieren aktivierte Warnungswellenwarnungen Fehler. Warnnungswelle 5 Diagnose wurden in C# 9 hinzugefügt. Warnungswellen 6-Diagnose wurden in C# 10 hinzugefügt. Warnungswellen 7-Diagnose wurden in C# 11 hinzugefügt. Warnungswellen 8-Diagnose wurde in C# 12 hinzugefügt.

CS9123 – Die Verwendung der Adresse einer lokalen Variablen oder eines Parameters in der asynchronen Methode kann zu einem GC-Loch führen.

Warnungswelle 8

Der &-Operator darf nicht für Parameter oder lokale Variablen in asynchronen Methoden verwendet werden. Mit dem folgenden Code wird CS9123 generiert:

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

CS8981 – Der Typname enthält nur kleingeschriebene ASCII-Zeichen.

Warnungswelle 7

Alle neuen Schlüsselwörter, die für C# hinzugefügt werden, sind alle ASCII-Zeichen in Kleinbuchstaben. Diese Warnung stellt sicher, dass keiner Ihrer Typen mit zukünftigen Schlüsselwörtern in Konflikt geraten kann. Der folgende Code erzeugt CS8981:

public class lowercasename
{
}

Sie können diese Warnung beheben, indem Sie den Typ umbenennen, um mindestens ein Nicht-Kleinbuchstaben-ASCII-Zeichen einzuschließen, z. B. ein Großbuchstaben, eine Ziffer oder einen Unterstrich.

CS8826 – Partielle Methodendeklarationen weisen Signaturunterschiede auf.

Warnungswelle 6

Diese Warnung korrigiert einige Inkonsistenzen bei der Meldung von Unterschieden zwischen partiellen Methodensignaturen. Der Compiler hat immer einen Fehler gemeldet, wenn die partiellen Methodensignaturen unterschiedliche CLR-Signaturen erstellt haben. Nun meldet der Compiler CS8826, wenn die Signaturen syntaktisch unterschiedlich sind C#. Betrachten Sie folgendes partielles Schema:

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

Die folgende partielle Klassenimplementierung generiert mehrere Beispiele für 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) { }
}

Hinweis

Wenn die Implementierung einer Methode einen nicht nullfähigen Verweistyp verwendet, wenn die andere Deklaration nullfähige Verweistypen akzeptiert, wird CS8611 anstelle von CS8826 generiert.

Um eine Instanz dieser Warnungen zu beheben, stellen Sie sicher, dass die beiden Signaturen übereinstimmen.

CS7023 – Ein statischer Typ wird in einem Ausdruck 'is' oder 'as' verwendet.

Warnungswelle 5

Die is- und as-Ausdrücke geben immer für einen statischen Typ false zurück, da Sie keine Instanzen eines statischen Typs erstellen können. Der folgende Code erzeugt 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");
    }
}

Der Compiler meldet diese Warnung, da der Typtest nie erfolgreich sein kann. Um diese Warnung zu korrigieren, entfernen Sie den Test, und entfernen Sie den Code, der nur ausgeführt wird, wenn der Test erfolgreich war. Im vorherigen Beispiel wird die else-Klausel immer ausgeführt. Der Methodentext könnte durch diese einzelne Zeile ersetzt werden:

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

CS8073 – Das Ergebnis des Ausdrucks ist immer 'false' (oder 'true').

Warnungswelle 5

Die == Operatoren und != geben immer false (oder true) zurück, wenn eine Instanz eines struct Typs mit null verglichen wird. Der folgende Code veranschaulicht diese Warnung. Angenommen S ist eine struct , die operator == und operator != definiert:

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

Um diesen Fehler zu beheben, entfernen Sie die NULL-Prüfung und den Code, der ausgeführt wird, wenn das Objekt null ist.

CS8848 – Operator 'from' kann hier aufgrund der Rangfolge nicht verwendet werden. Verwenden Sie Klammern, um mehrdeutig zu sein.

Warnungswelle 5

Diese Warnung wird in den folgenden Beispielen veranschaulicht. Der Ausdruck wird aufgrund der Rangfolge der Operatoren falsch gebunden.

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

Um diesen Fehler zu beheben, setzen Sie Klammern um den Abfrageausdruck:

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

Member müssen vollständig zugewiesen werden, Verwendung nicht zugewiesener Variablen (CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS8886, CS8887)

Warnungswelle 5

Mehrere Warnungen verbessern die eindeutige Zuordnungsanalyse für struct Typen, die in importierten Assemblys deklariert sind. Alle diese neuen Warnungen werden generiert, wenn eine Anweisung in einer importierten Assembly ein nicht zugängliches Feld (in der Regel ein private-Feld) eines Verweistyps enthält, wie im folgenden Beispiel gezeigt:

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

Die folgenden Beispiele zeigen die Warnungen, die aus der verbesserten eindeutigen Zuordnungsanalyse generiert wurden:

  • CS8880: Die automatisch implementierte Eigenschaft „Property“ muss vollständig zugewiesen werden, bevor die Kontrolle an den Aufrufer zurückgegeben wird.
  • CS8881: Das Feld „Feld“ muss vollständig zugewiesen sein, bevor die Kontrolle an den Aufrufer zurückgegeben wird.
  • CS8882: Der Out-Parameter „parameter“ muss zugewiesen werden, bevor die Steuerung die aktuelle Methode verlässt.
  • CS8883: Verwendung der möglicherweise nicht zugewiesenen automatisch implementierten Eigenschaft "Property".
  • CS8884:Verwendung des möglicherweise nicht zugewiesenen Felds 'Feld'.
  • CS8885: Das Objekt "this" kann nicht verwendet werden, bevor alle Felder zugewiesen wurden.
  • CS8886: Verwendung des nicht zugewiesenen Ausgabeparameters 'parameterName'.
  • CS8887: Verwendung nicht zugewiesener lokaler Variable "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;
    }
}

Sie können eine dieser Warnungen beheben, indem Sie die importierte Struktur initialisieren oder dem Standardwert zuweisen:

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 - Die Methode wird nicht als Einstiegspunkt verwendet, weil der synchroner Einstiegspunkt „method“ gefunden wurde.

Warnungswelle 5

Diese Warnung wird für alle asynchronen Einstiegspunktkandidaten generiert, wenn Sie über mehrere gültige Einstiegspunkte verfügen, einschließlich eines oder mehrerer synchroner Einstiegspunkt.

Im folgenden Beispiel wird der Fehler CS8892 generiert:

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

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

Hinweis

Der Compiler verwendet immer den synchronen Einstiegspunkt. Wenn mehrere synchrone Einstiegspunkte vorhanden sind, erhalten Sie einen Compilerfehler.

Um diese Warnung zu beheben, entfernen oder benennen Sie den asynchronen Einstiegspunkt um.

CS8897 - Statische Typen können nicht als Parameter verwendet werden

Warnungswelle 5

Member einer Schnittstelle können keine Parameter deklarieren, deren Typ eine statische Klasse ist. Der folgende Code veranschaulicht sowohl CS8897 als auch CS8898:

public static class Utilities
{
    // elided
}

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

    // CS8898
    public Utilities GetUtility();
}

Um diese Warnung zu beheben, ändern Sie den Parametertyp, oder entfernen Sie die Methode.

CS8898 - statische Typen können nicht als Rückgabetypen verwendet werden.

Warnungswelle 5

Member einer Schnittstelle können keinen Rückgabetyp deklarieren, der eine statische Klasse ist. Der folgende Code veranschaulicht sowohl CS8897 als auch CS8898:

public static class Utilities
{
    // elided
}

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

    // CS8898
    public Utilities GetUtility();
}

Um diese Warnung zu beheben, ändern Sie den Rückgabetyp, oder entfernen Sie die Methode.