C# Figyelmeztető hullámok
A C#-fordító minden egyes kiadásában új figyelmeztetések és hibák jelennek meg. Ha új figyelmeztetések jelenthetők meg a meglévő kódon, ezeket a figyelmeztetéseket egy figyelmeztető hullámnak nevezett opt-in rendszerben vezetik be. A bejelentkezési rendszer azt jelenti, hogy nem szabad új figyelmeztetéseket látnia a meglévő kódon anélkül, hogy lépéseket kellene tennie az engedélyezésük érdekében. A figyelmeztető hullámok a projektfájl AnalysisLevel elemével engedélyezve vannak. Ha <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
meg van adva, az engedélyezett figyelmeztetőhullám-figyelmeztetések hibákat okoznak. Az 5. figyelmeztető hullám diagnosztikái a C# 9-ben lettek hozzáadva. A 6. figyelmeztető hullám diagnosztikái a C# 10-ben lettek hozzáadva. A 7. figyelmeztető hullám diagnosztikái a C# 11-ben lettek hozzáadva. A 8. figyelmeztető hullám diagnosztikái a C# 12-ben lettek hozzáadva.
CS9123 – A helyi vagy paraméter aszinkron metódusban való címének megadása GC-lyukat hozhat létre.
Figyelmeztető hullám 8
Az &
operátor nem használható paramétereken vagy helyi változókon az aszinkron metódusokban.
A következő kód állítja elő a CS9123-at:
public static async Task LogValue()
{
int x = 1;
unsafe {
int* y = &x;
Console.WriteLine(*y);
}
await Task.Delay(1000);
}
A C# 13-tól kezdődően ez a kód fordítóhibát okoz.
CS8981 – A típusnév csak kisbetűs ascii karaktereket tartalmaz.
Figyelmeztető hullám 7
A C#-hoz hozzáadott új kulcsszavak mind kisbetűs ASCII-karakterek lesznek. Ez a figyelmeztetés biztosítja, hogy egyik típus sem ütközik a jövőbeli kulcsszavakkal. A következő kód állítja elő a CS8981-et:
public class lowercasename
{
}
Ezt a figyelmeztetést úgy kezelheti, ha átnevezi a típust, hogy legalább egy nem kisbetűs ASCII-karaktert( például nagybetűt, számjegyet vagy aláhúzásjelet) tartalmazzon.
CS8826 – A részleges metódusdeklarációk aláírási eltérésekkel rendelkeznek.
6. figyelmeztetési hullám
Ez a figyelmeztetés kijavít néhány inkonzisztenciát a részleges metódus-aláírások közötti jelentési különbségekben. A fordító mindig hibát jelentett, amikor a részleges metódus-aláírások különböző CLR-aláírásokat hoztak létre. A fordító most a CS8826-ot jelenti, ha az aláírások szintaktikailag eltérőek C#. Vegye figyelembe a következő részleges osztályt:
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);
}
Az alábbi részleges osztály implementációja számos példát hoz létre a CS8626-ra:
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) { }
}
Feljegyzés
Ha egy metódus megvalósítása nem null értékű hivatkozástípust használ, amikor a másik deklaráció null értékű hivatkozástípusokat fogad el, a CS8611 a CS8826 helyett jön létre.
A figyelmeztetések bármelyik példányának kijavításához győződjön meg arról, hogy a két aláírás egyezik.
CS7023 – Statikus típust használ egy "is" vagy "as" kifejezés.
5. figyelmeztetési hullám
A is
kifejezések és as
a kifejezések mindig statikus típushoz térnek vissza false
, mert nem hozhatók létre statikus típusú példányok. A következő kód állítja elő a CS7023-at:
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");
}
}
A fordító azért jelenti ezt a figyelmeztetést, mert a típusteszt soha nem lehet sikeres. A figyelmeztetés kijavításához távolítsa el a tesztet, és távolítsa el a végrehajtott kódot, ha a teszt sikeres volt. Az előző példában a else
záradék mindig végrehajtásra kerül. A metódus törzsét a következő egyetlen sorra cserélheti:
Console.WriteLine("o is not an instance of a static class");
CS8073 – A kifejezés eredménye mindig "hamis" (vagy igaz).
5. figyelmeztetési hullám
Az ==
és !=
az operátorok mindig visszaadják false
(vagy true
) a típuspéldányok struct
null
összehasonlítását. Az alábbi kód bemutatja ezt a figyelmeztetést. Tegyük felS
, hogy a struct
következőt definiáljaoperator ==
: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...
}
A hiba kijavításához távolítsa el az objektum null
esetén végrehajtandó null ellenőrzést és kódot.
CS8848 – A "from" operátor nem használható itt az elsőbbség miatt. Zárójelek használatával egyértelműsíthet.
5. figyelmeztetési hullám
Az alábbi példák ezt a figyelmeztetést mutatják be. A kifejezés helytelenül kötődik az operátorok elsőbbsége miatt.
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];
A hiba kijavításához zárójeleket helyezzen el a lekérdezési kifejezés körül:
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)];
A tagokat teljes mértékben ki kell osztani. Nem hozzárendelt változó használata (CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS8886, CS8887)
5. figyelmeztetési hullám
Számos figyelmeztetés javítja az importált szerelvényekben deklarált típusok határozott hozzárendelési elemzését struct
. Ezek az új figyelmeztetések akkor jönnek létre, ha egy importált szerelvény egy szerkezetében egy hivatkozástípus elérhetetlen mezője (általában egy private
mező) szerepel, ahogyan az alábbi példában látható:
public struct Struct
{
private string data = String.Empty;
public Struct() { }
}
Az alábbi példák a továbbfejlesztett határozott hozzárendelés-elemzésből származó figyelmeztetéseket mutatják be:
- CS8880: Az automatikusan megvalósított "Tulajdonság" tulajdonságot teljes mértékben ki kell osztani, mielőtt a rendszer visszaadja a vezérlést a hívónak.
- CS8881: A "mező" mezőt teljes mértékben ki kell osztani, mielőtt a vezérlő visszakerül a hívóhoz.
- CS8882: A "paraméter" kimenő paramétert hozzá kell rendelni, mielőtt a vezérlő elhagyja az aktuális metódust.
- CS8883: Valószínűleg nem hozzárendelt, automatikusan implementált "Tulajdonság" tulajdonság használata.
- CS8884: A "Mező" esetleg nem hozzárendelt mező használata
- CS8885: Az "ez" objektum nem használható az összes mező hozzárendelése előtt.
- CS8886: A "parameterName" nem hozzárendelt kimeneti paraméter használata.
- CS8887: A "variableName" nem hozzárendelt helyi változó használata
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;
}
}
Ezen figyelmeztetések bármelyikét kijavíthatja, ha inicializálja vagy hozzárendeli az importált szerkezetet az alapértelmezett értékhez:
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 – A metódus nem használható belépési pontként, mert egy szinkron belépési pont "metódus" található.
5. figyelmeztetési hullám
Ez a figyelmeztetés akkor jön létre az összes aszinkron belépési pont jelöltjén, ha több érvényes belépési ponttal rendelkezik, beleértve egy vagy több szinkron belépési pontot is.
Az alábbi példa a CS8892-t hozza létre:
public static void Main()
{
RunProgram();
}
// CS8892
public static async Task Main(string[] args)
{
await RunProgramAsync();
}
Feljegyzés
A fordító mindig a szinkron belépési pontot használja. Több szinkron belépési pont esetén fordítóhiba jelenik meg.
A figyelmeztetés kijavításához távolítsa el vagy nevezze át az aszinkron belépési pontot.
CS8897 – Statikus típusok nem használhatók paraméterekként
5. figyelmeztetési hullám
Az interfész tagjai nem deklarálhatnak olyan paramétereket, amelyek típusa statikus osztály. Az alábbi kód a CS8897-et és a CS8898-at is bemutatja:
public static class Utilities
{
// elided
}
public interface IUtility
{
// CS8897
public void SetUtility(Utilities u);
// CS8898
public Utilities GetUtility();
}
A figyelmeztetés kijavításához módosítsa a paraméter típusát, vagy távolítsa el a metódust.
CS8898 – A statikus típusok nem használhatók visszatérési típusokként
5. figyelmeztetési hullám
A felület tagjai nem deklarálhatnak statikus osztályt tartalmazó visszatérési típust. Az alábbi kód a CS8897-et és a CS8898-at is bemutatja:
public static class Utilities
{
// elided
}
public interface IUtility
{
// CS8897
public void SetUtility(Utilities u);
// CS8898
public Utilities GetUtility();
}
A figyelmeztetés kijavításához módosítsa a visszatérési típust, vagy távolítsa el a metódust.