Sdílet prostřednictvím


Vlny upozornění jazyka C#

V každé verzi kompilátoru jazyka C# je možné zavést nová upozornění a chyby. Pokud by se nová upozornění mohla hlásit u existujícího kódu, tato upozornění se zavádějí v rámci systému pro vyjádření souhlasu , který se označuje jako vlna upozornění. Systém výslovného souhlasu znamená, že byste neměli zobrazovat nová upozornění pro stávající kód, aniž byste je povolili. Pokud <TreatWarningsAsErrors>true</TreatWarningsAsErrors> je zadána, povolená upozornění vln generují chyby. V jazyce C# 9 byla přidána diagnostika s upozorněním 5. V jazyce C# 10 byla přidána diagnostika s upozorněním 6. V jazyce C# 11 byla přidána diagnostika s upozorněním 7. V jazyce C# 12 byla přidána diagnostika s upozorněním 8. V jazyce C# 13 byla přidána diagnostika vlny varování 9.

Počínaje .NET 7 SDK (C# 11) systém sestavení nastavuje úrovně varování podle následujících pravidel:

  • AnalysisLevel sleduje aktuální TFM, pokud není zadaný.
  • AnalysisLevel je nastaven na nejnovější, pokud aktuální TFM je 'latest' TFM (podle vlastnosti, kterou potřebujeme aktualizovat)
  • Úroveň varování by měla sledovat aktuální TFM, pokud není zadaná.
  • WarningLevel by neměl přepsat hodnotu zadanou uživatelem
  • Hodnota WarningLevel by měla být nastavena na hodnotu 4, pokud je projektem rozhraní .NET Framework.

U sadě SDK starších než .NET 7 vždy přepisoval AnalysisLevel úroveň WarningLevel.

CS9123 - Převzetí adresy místního nebo parametru v asynchronní metodě může vytvořit otvor GC.

Varovná vlna 8

Operátor & by neměl být použit u parametrů nebo místních proměnných v asynchronních metodách. Následující kód vytvoří CS9123:

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

CS8981 – Název typu obsahuje pouze znaky ASCII s malých písmeny.

Výstražná vlna 7

Všechna nová klíčová slova přidaná pro jazyk C# budou znaky ASCII s malých písmeny. Toto upozornění zajišťuje, že žádný z vašich typů není v konfliktu s budoucími klíčovými slovy. Následující kód vytvoří CS8981:

public class lowercasename
{
}

Toto upozornění můžete vyřešit přejmenováním typu tak, aby obsahoval alespoň jeden znak ASCII bez malého písmena, například velké písmeno, číslici nebo podtržítko.

CS8826 – Deklarace částečné metody mají rozdíly mezi podpisy.

Výstražná vlna 6

Toto upozornění opraví některé nekonzistence v hlášení rozdílů mezi částečnými podpisy metody. Kompilátor vždy oznámil chybu, když podpisy částečné metody vytvořily různé podpisy CLR. Kompilátor teď hlásí CS8826, když jsou podpisy syntakticky odlišné C#. Vezměte v úvahu následující částečnou třídu:

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

Následující částečná implementace třídy generuje několik příkladů 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) { }
}

Poznámka:

Pokud implementace metody používá nenulový odkazový typ, pokud druhá deklarace přijímá odkazové typy s možnou hodnotou null, cs8611 je generován místo CS8826.

Pokud chcete opravit jakoukoli instanci těchto upozornění, ujistěte se, že se tyto dva podpisy shodují.

CS7023 – Statický typ se používá ve výrazu 'is' nebo 'as'.

Výstražná vlna 5

Výrazy is se as vždy vrátí false pro statický typ, protože nemůžete vytvářet instance statického typu. Následující kód vytvoří 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");
    }
}

Kompilátor hlásí toto upozornění, protože test typu nemůže být nikdy úspěšný. Chcete-li toto upozornění opravit, odeberte test a odeberte veškerý kód spuštěný pouze v případě, že test proběhl úspěšně. V předchozím příkladu else se klauzule vždy spustí. Text této metody můžete nahradit jedním řádkem:

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

CS8073 – výsledek výrazu je vždy false (nebo true).

Výstražná vlna 5

Operátory == a vždy vrací != (nebofalse) při porovnávání instance true typu s structnull . Toto upozornění ukazuje následující kód. Předpokládejme S , že definuje structoperator == a 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...
}

Chcete-li tuto chybu opravit, odeberte kontrolu null a kód, který by se spustil, pokud je nullobjekt .

CS8848 – Operátor from se tady nedá použít kvůli prioritě. K nejednoznačnosti použijte závorky.

Výstražná vlna 5

Následující příklady ukazují toto upozornění. Výraz se nesprávně sváže z důvodu priority operátorů.

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

Pokud chcete tuto chybu opravit, umístěte závorky kolem výrazu dotazu:

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

Členové musí být plně přiřazeni. Použití nepřiřazené proměnné (CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS8886, CS8887)

Výstražná vlna 5

Několikupozorněních struct Všechna tato nová upozornění se generují, když struktura v importovaném sestavení obsahuje nepřístupné pole (obvykle private pole) typu odkazu, jak je znázorněno v následujícím příkladu:

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

Následující příklady ukazují upozornění vygenerovaná z vylepšené analýzy přiřazení:

  • CS8880: Automaticky implementovaná vlastnost Property musí být plně přiřazena před vrácením ovládacího prvku volajícímu.
  • CS8881: Pole pole musí být plně přiřazeno, než se ovládací prvek vrátí volajícímu.
  • CS8882: Parametr out "parameter" musí být přiřazen před opuštěním aktuální metody.
  • CS8883: Použití pravděpodobně nepřiřazené automaticky implementované vlastnosti Property.
  • CS8884: Použití pravděpodobně nepřiřazeného pole Pole
  • CS8885: Objekt this nelze použít před přiřazením všech polí.
  • CS8886: Použití nepřiřazeného výstupního parametru parameter 'parameterName'.
  • CS8887: Použití nepřiřazené místní proměnné 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;
    }
}

Některá z těchto upozornění můžete opravit inicializací nebo přiřazením importované struktury k její výchozí hodnotě:

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 – Metoda nebude použita jako vstupní bod, protože byla nalezena synchronní vstupní bod "metoda".

Výstražná vlna 5

Toto upozornění se vygeneruje pro všechny kandidáty asynchronního vstupního bodu, pokud máte více platných vstupních bodů, včetně jednoho nebo více synchronních vstupních bodů.

Následující příklad vygeneruje CS8892:

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

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

Poznámka:

Kompilátor vždy používá synchronní vstupní bod. Pokud existuje více synchronních vstupních bodů, zobrazí se chyba kompilátoru.

Pokud chcete toto upozornění opravit, odeberte nebo přejmenujte asynchronní vstupní bod.

CS8897 – Statické typy nejde použít jako parametry

Výstražná vlna 5

Členové rozhraní nemohou deklarovat parametry, jejichž typ je statická třída. Následující kód ukazuje CS8897 i CS8898:

public static class Utilities
{
    // elided
}

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

    // CS8898
    public Utilities GetUtility();
}

Chcete-li toto upozornění opravit, změňte typ parametru nebo odeberte metodu.

CS8898 – statické typy nejde použít jako návratové typy

Výstražná vlna 5

Členové rozhraní nemohou deklarovat návratový typ, který je statickou třídou. Následující kód ukazuje CS8897 i CS8898:

public static class Utilities
{
    // elided
}

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

    // CS8898
    public Utilities GetUtility();
}

Chcete-li toto upozornění opravit, změňte návratový typ nebo odeberte metodu.