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 volitelného systému označovaného 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 na vlně upozornění 7. V jazyce C# 12 byly přidány diagnostiky varování vlna 8. V jazyce C# 13 byla přidána diagnostika vlny varování 9. V C# verzi 14 byla přidána diagnostická sada upozornění, označená jako wave 10.

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.

CS9265 – Pole není nikdy přiřazováno jako reference a vždy bude mít výchozí hodnotu.

Varovná vlna 10

Pole ref v ref struct, které nikdy není přiřazeno odkazem, má vždy svou výchozí hodnotu, což je null reference. Následující kód vytvoří CS9265:

ref struct Container
{
    // CS9265: Field 'value' is never ref-assigned to,
    // and will always have its default value (null reference)
    public ref int value;
}

Pokud chcete toto upozornění vyřešit, přiřaďte pole v inicializátoru pole nebo ve všech cestách ke kódu konstruktoru. Případně odeberte ref modifikátor z deklarace pole, pokud pole nemusí být odkazem.

CS9123 – Operátor &by neměl být použit u parametrů nebo místních proměnných v asynchronních metodách.

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ými písmeny. Názvy se mohou pro tento jazyk stát vyhrazenými.

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ých metod mají rozdíly v signaturách.

Výstražná vlna 6

Toto upozornění opraví některé nesourodosti ve zprávách o rozdílech mezi částečnými definicemi metod. Kompilátor vždy oznámil chybu, když se podpisy částečných metod lišily od podpisů CLR. Kompilátor nyní hlásí CS8826, když jsou podpisy v jazyce C# syntakticky odlišné. 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, když druhá deklarace přijímá odkazové typy s možnou hodnotou null, je generován CS8611 místo CS8826.

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

CS7023 – druhý operand operátoru is nebo as nemusí být statický typ.

Výstražná vlna 5

Výrazy is a as vždy vracejí false pro statický typ, protože u statického typu nelze vytvářet instance. 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 se klauzule else 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 hodnota, protože hodnota typu type 'type' se nikdy nerovná hodnotě null typu 'type'

Výstražná vlna 5

Operátory == a != vždy vracejí false (nebo true) při porovnávání instance typu struct s null. Toto upozornění ukazuje následující kód. Předpokládejme, že S je struct, který definuje operator == 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 zde 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ěkolik upozornění zlepšuje analýzu definitivního přiřazení pro typy struct deklarované v importovaných sestavách. 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. Zvažte aktualizaci na jazykovou verzi 'version' pro automatické nastavení vlastnosti na výchozí hodnotu.
  • CS8881: Pole 'field' musí být plně přiřazeno, než se řízení vrátí volajícímu. Zvažte aktualizaci na jazykovou verzi „version“ pro automatické nastavení pole na výchozí hodnotu.
  • 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í pole 'Field', které možná není přiřazeno
  • CS8885: Objekt this nelze použít před přiřazením všech polí. Zvažte aktualizaci na jazykovou verzi 'version', aby se nepřiřazená pole automaticky nastavila na výchozí hodnoty.
  • CS8886: Použití nepřiřazené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 byl nalezen synchronní vstupní bod 'method'.

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