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. Vlny upozornění jsou povoleny pomocí elementu AnalysisLevel ve vašem souboru projektu. 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.
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);
}
Počínaje jazykem C# 13 tento kód generuje chybu kompilátoru.
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í false
(nebotrue
) při porovnávání instance struct
typu s null
!=
. Toto upozornění ukazuje následující kód. Předpokládejme S
, že definuje struct
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 null
objekt .
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: Před opuštěním aktuální metody musí být přiřazen výstupní parametr "parameter".
- 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.