C#-varningsvågor
Nya varningar och fel kan introduceras i varje version av C#-kompilatorn. När nya varningar kan rapporteras om befintlig kod introduceras dessa varningar i ett opt-in-system som kallas för en varningsvåg. Opt-in-systemet innebär att du inte bör se nya varningar om befintlig kod utan att vidta åtgärder för att aktivera dem. Varningsvågor aktiveras med analysislevel-elementet i projektfilen. När <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
har angetts genererar aktiverade varningsvågor fel. Varningsvåg 5-diagnostik lades till i C# 9. Varningsvåg 6-diagnostik lades till i C# 10. Diagnostik för varningsvåg 7 lades till i C# 11. Varningsvåg 8-diagnostik lades till i C# 12.
CS9123 – Om du tar adressen till lokal eller parameter i asynkron metod kan du skapa ett GC-hål.
Varningsvåg 8
Operatorn &
ska inte användas på parametrar eller lokala variabler i asynkrona metoder.
Följande kod genererar CS9123:
public static async Task LogValue()
{
int x = 1;
unsafe {
int* y = &x;
Console.WriteLine(*y);
}
await Task.Delay(1000);
}
Från och med C# 13 genererar den här koden ett kompilatorfel.
CS8981 – Typnamnet innehåller endast gemener ascii-tecken.
Varningsvåg 7
Alla nya nyckelord som läggs till för C# är alla gemena ASCII-tecken. Den här varningen säkerställer att ingen av dina typer är i konflikt med framtida nyckelord. Följande kod genererar CS8981:
public class lowercasename
{
}
Du kan åtgärda den här varningen genom att byta namn på typen så att den innehåller minst ett ASCII-tecken som inte är gemener, till exempel versaler, siffror eller understreck.
CS8826 – Partiella metoddeklarationer har signaturskillnader.
Varningsvåg 6
Den här varningen korrigerar vissa inkonsekvenser i rapporteringsskillnader mellan partiella metodsignaturer. Kompilatorn rapporterade alltid ett fel när de partiella metodsignaturerna skapade olika CLR-signaturer. Nu rapporterar kompilatorn CS8826 när signaturerna är syntaktiskt olika C#. Överväg följande partiella klass:
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);
}
Följande partiella klassimplementering genererar flera exempel på 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) { }
}
Kommentar
Om implementeringen av en metod använder en icke-nullbar referenstyp när den andra deklarationen accepterar null-referenstyper genereras CS8611 i stället för CS8826.
Om du vill åtgärda alla instanser av dessa varningar kontrollerar du att de två signaturerna matchar.
CS7023 – En statisk typ används i ett "is" eller "as"-uttryck.
Varningsvåg 5
Uttrycken is
och as
returnerar false
alltid för en statisk typ eftersom du inte kan skapa instanser av en statisk typ. Följande kod genererar 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");
}
}
Kompilatorn rapporterar den här varningen eftersom typtestet aldrig kan lyckas. Åtgärda varningen genom att ta bort testet och ta bort all kod som körs endast om testet lyckades. I föregående exempel else
körs satsen alltid. Du kan ersätta metodtexten med den enda raden:
Console.WriteLine("o is not an instance of a static class");
CS8073 – Resultatet av uttrycket är alltid "falskt" (eller "sant").
Varningsvåg 5
Operatorerna ==
och returnerar false
alltid (eller true
) när en instans av en typ jämförs struct
med null
!=
. Följande kod visar den här varningen. Anta S
att är en struct
som definierar operator ==
och 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...
}
Åtgärda det här felet genom att ta bort null-kontrollen och koden som skulle köras om objektet är null
.
CS8848 – Operatorn "från" kan inte användas här på grund av prioritet. Använd parenteser för att skilja sig åt.
Varningsvåg 5
Följande exempel visar den här varningen. Uttrycket binder felaktigt på grund av operatorernas prioritet.
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];
Åtgärda det här felet genom att placera parenteser runt frågeuttrycket:
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)];
Medlemmar måste vara fullständigt tilldelade. Användning av otilldelade variabler (CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS8886, CS8887)
Varningsvåg 5
Flera varningar förbättrar den definitiva tilldelningsanalysen för struct
typer som deklarerats i importerade sammansättningar. Alla dessa nya varningar genereras när en struct i en importerad sammansättning innehåller ett otillgängligt fält (vanligtvis ett private
fält) av en referenstyp, som visas i följande exempel:
public struct Struct
{
private string data = String.Empty;
public Struct() { }
}
Följande exempel visar varningarna som genereras från den förbättrade definitiva tilldelningsanalysen:
- CS8880: Den automatiskt implementerade egenskapen "Property" måste tilldelas helt innan kontrollen returneras till anroparen.
- CS8881: Fältet fält måste tilldelas fullständigt innan kontrollen returneras till anroparen.
- CS8882: Out-parametern "parameter" måste tilldelas till innan kontrollen lämnar den aktuella metoden.
- CS8883: Användning av den eventuellt otilldelade automatiskt implementerade egenskapen "Property".
- CS8884: Användning av eventuellt otilldelade fält "Fält"
- CS8885: Det här objektet kan inte användas innan alla dess fält har tilldelats.
- CS8886: Användning av den otilldelade utdataparametern "parameterName".
- CS8887: Användning av den otilldelade lokala variabeln "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;
}
}
Du kan åtgärda någon av dessa varningar genom att initiera eller tilldela den importerade structen till standardvärdet:
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 – Metoden används inte som startpunkt eftersom en synkron startpunkt för metoden hittades.
Varningsvåg 5
Den här varningen genereras på alla asynkrona startpunktskandidater när du har flera giltiga startpunkter, inklusive en eller flera synkrona startpunkter.
I följande exempel genereras CS8892:
public static void Main()
{
RunProgram();
}
// CS8892
public static async Task Main(string[] args)
{
await RunProgramAsync();
}
Kommentar
Kompilatorn använder alltid den synkrona startpunkten. Om det finns flera synkrona startpunkter får du ett kompilatorfel.
Åtgärda varningen genom att ta bort eller byta namn på den asynkrona startpunkten.
CS8897 – Statiska typer kan inte användas som parametrar
Varningsvåg 5
Medlemmar i ett gränssnitt kan inte deklarera parametrar vars typ är en statisk klass. Följande kod visar både CS8897 och CS8898:
public static class Utilities
{
// elided
}
public interface IUtility
{
// CS8897
public void SetUtility(Utilities u);
// CS8898
public Utilities GetUtility();
}
Åtgärda varningen genom att ändra parametertypen eller ta bort metoden.
CS8898 – statiska typer kan inte användas som returtyper
Varningsvåg 5
Medlemmar i ett gränssnitt kan inte deklarera en returtyp som är en statisk klass. Följande kod visar både CS8897 och CS8898:
public static class Utilities
{
// elided
}
public interface IUtility
{
// CS8897
public void SetUtility(Utilities u);
// CS8898
public Utilities GetUtility();
}
Åtgärda varningen genom att ändra returtypen eller ta bort metoden.