Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Nowe ostrzeżenia i błędy można wprowadzić w każdej wersji kompilatora języka C#. Gdy nowe ostrzeżenia mogą być zgłaszane w istniejącym kodzie, ostrzeżenia te są wprowadzane w systemie zgody nazywanym falą ostrzegawczą. System zgody oznacza, że nie powinny być wyświetlane nowe ostrzeżenia dotyczące istniejącego kodu bez podejmowania działań w celu ich włączenia. Po określeniu <TreatWarningsAsErrors>true</TreatWarningsAsErrors>, włączone ostrzeżenia dotyczące fali generują błędy. Dodano diagnostykę z falą ostrzegawczą 5 w języku C# 9. Dodano diagnostyki ostrzeżeń fali 6 w języku C# 10. Dodano diagnostykę z falą ostrzegawczą 7 w języku C# 11. Dodano diagnostykę fali ostrzeżeń 8 w języku C# 12. Dodano diagnostykę z falą ostrzegawczą 9 w języku C# 13. Dodano diagnostykę fali ostrzeżeń 10 w C# 14.
Począwszy od zestawu .NET 7 SDK (C# 11), system kompilacji ustawia fale ostrzegawcze z następującymi regułami:
- AnalysisLevel śledzi bieżący TFM, jeśli nie jest określony
- Właściwość AnalysisLevel jest ustawiona na najnowszą, jeśli bieżący TFM jest "najnowszym" TFM (zdefiniowanym przez właściwość, którą musimy zaktualizować).
- WarningLevel powinien śledzić bieżący TFM, jeśli nie zostanie określony
- WarningLevel nie powinien zastępować wartości podanej przez użytkownika
- Wartość WarningLevel powinna być ustawiona na 4, jeśli projekt jest projektem .NET Framework
W przypadku zestawów SDK wcześniejszych niż .NET 7 funkcja AnalysisLevel zawsze zastępuje wartość WarningLevel.
CS9265 — pole nigdy nie jest przypisywane jako ref i zawsze będzie miało wartość domyślną
Fala ostrzegawcza 10
ref Pole w obiekcieref struct, do którego nigdy nie przypisano odwołania, zawsze ma wartość domyślną, którą jest referencja o wartości null. Poniższy kod tworzy 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;
}
Aby rozwiązać to ostrzeżenie, można przypisać pole przez referencję w inicjatorze pola lub we wszystkich ścieżkach kodu konstruktora. Alternatywnie usuń ref modyfikator z deklaracji pola, jeśli pole nie musi być odwołaniem.
CS9123 — operator "&" nie powinien być używany w parametrach ani zmiennych lokalnych w metodach asynchronicznych
Fala ostrzegawcza 8
Operator & nie powinien być używany w parametrach ani zmiennych lokalnych w metodach asynchronicznych.
Poniższy kod tworzy CS9123:
public static async Task LogValue()
{
int x = 1;
unsafe {
int* y = &x;
Console.WriteLine(*y);
}
await Task.Delay(1000);
}
CS8981 — nazwa typu zawiera tylko małe litery znaków ascii. Takie nazwy mogą stać się zarezerwowane dla języka.
Fala ostrzegawcza 7
Wszystkie nowe słowa kluczowe dodane dla języka C# będą mieć małe litery znaków ASCII. To ostrzeżenie gwarantuje, że żaden z typów nie powoduje konfliktu z przyszłymi słowami kluczowymi. Poniższy kod tworzy CS8981:
public class lowercasename
{
}
To ostrzeżenie można rozwiązać, zmieniając nazwę typu, aby uwzględnić co najmniej jeden znak ASCII, taki jak wielkie litery, cyfra lub podkreślenie.
CS8826 — Deklaracje metody częściowej mają różnice w sygnaturze.
Fala ostrzegawcza 6
To ostrzeżenie poprawia pewne niespójności w raportowaniu różnic między częściowymi sygnaturami metod. Kompilator zawsze zgłaszał błąd, gdy sygnatury metody częściowej utworzyły różne sygnatury CLR. Teraz kompilator raportuje CS8826, gdy sygnatury są składniowo różne w języku C#. Rozważmy następującą klasę częściową:
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);
}
Następująca implementacja klasy częściowej generuje kilka przykładów 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) { }
}
Uwaga
Jeśli implementacja metody używa typu odwołania non-null, gdy inna deklaracja dopuszcza typy referencyjne dopuszczające wartości null, generowany jest CS8611 zamiast CS8826.
Aby naprawić dowolne wystąpienie tych ostrzeżeń, upewnij się, że dwa podpisy są zgodne.
CS7023 — drugi operand operatora "is" lub "as" nie może być typem statycznym
Fala ostrzegawcza 5
Wyrażenia is i as zawsze zwracają false dla typu statycznego, ponieważ nie można tworzyć wystąpień typu statycznego. Poniższy kod tworzy 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");
}
}
Kompilator zgłasza to ostrzeżenie, ponieważ test typu nigdy nie powiedzie się. Aby poprawić to ostrzeżenie, usuń test i usuń dowolny kod wykonany tylko wtedy, gdy test zakończył się pomyślnie. W poprzednim przykładzie klauzula else jest zawsze wykonywana. Tę treść metody można zastąpić pojedynczym wierszem:
Console.WriteLine("o is not an instance of a static class");
CS8073 — wynik wyrażenia jest zawsze "wartość", ponieważ wartość typu "type" nigdy nie jest równa wartości "null" typu "type"
Fala ostrzegawcza 5
Operatory == i != zawsze zwracają false (lub true) w porównaniu instancji typu struct do null. Poniższy kod demonstruje to ostrzeżenie. Załóżmy, że S jest struct, który definiuje operator == oraz 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...
}
Aby naprawić ten błąd, usuń sprawdzanie wartości null i kod, który będzie wykonywany, jeśli obiekt ma wartość null.
CS8848 — operator "from" nie może być używany tutaj z powodu pierwszeństwa. Użyj nawiasów, aby uściślić.
Fala ostrzegawcza 5
W poniższych przykładach pokazano to ostrzeżenie. Wyrażenie jest niepoprawnie powiązane ze względu na pierwszeństwo operatorów.
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];
Aby naprawić ten błąd, umieść nawiasy wokół wyrażenia zapytania:
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)];
Członkowie muszą być w pełni przypisani. Użycie nieprzypisanej zmiennej (CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS8886, CS8887)
Fala ostrzegawcza 5
Kilka ostrzeżeń poprawia określoną analizę przypisania dla struct typów zadeklarowanych w importowanych zestawach. Wszystkie te nowe ostrzeżenia są generowane, gdy struktura w zaimportowanym zestawie zawiera niedostępne pole (zwykle private pole) typu odwołania, jak pokazano w poniższym przykładzie:
public struct Struct
{
private string data = String.Empty;
public Struct() { }
}
W poniższych przykładach pokazano ostrzeżenia wygenerowane na podstawie ulepszonej analizy jednoznacznego przypisania.
- CS8880: Właściwość zaimplementowana automatycznie musi być w pełni przypisana przed zwróceniem kontrolki do obiektu wywołującego. Rozważ aktualizację do wersji językowej "version", aby automatycznie ustawić właściwość .
- CS8881: Pole "pole" musi być w pełni przypisane przed zwróceniem sterowania do wywołującego. Rozważ zaktualizowanie do wersji językowej "version", aby automatycznie ustawić pole jako domyślne.
- CS8882: Parametr
out'parametr' musi zostać przypisany, zanim opuszczona zostanie bieżąca metoda. - CS8883: Użycie prawdopodobnie nieprzypisanej automatycznie zaimplementowanej właściwości "Property".
- CS8884: Użycie prawdopodobnie nieprzypisanego pola "Pole"
- CS8885: Nie można użyć obiektu "this" zanim wszystkie jego pola zostaną przypisane. Rozważ aktualizację do wersji językowej "version" w celu automatycznego ustawienia nieprzypisanych pól.
- CS8886: Użyj nieprzypisanego parametru "parameterName".
- CS8887: Używanie nieprzypisanej zmiennej lokalnej "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;
}
}
Możesz naprawić dowolne z tych ostrzeżeń, inicjując lub przypisując zaimportowaną strukturę do jej wartości domyślnej:
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 nie będzie używana jako punkt wejścia, ponieważ znaleziono synchroniczny punkt wejścia 'method'.
Fala ostrzegawcza 5
To ostrzeżenie jest generowane dla wszystkich kandydatów do punktu wejścia asynchronicznego, gdy masz wiele prawidłowych punktów wejścia, w tym co najmniej jeden synchroniczny punkt wejścia.
Poniższy przykład generuje CS8892:
public static void Main()
{
RunProgram();
}
// CS8892
public static async Task Main(string[] args)
{
await RunProgramAsync();
}
Uwaga
Kompilator zawsze używa synchronicznego punktu wejścia. W przypadku wystąpienia wielu synchronicznych punktów wejścia występuje błąd kompilatora.
Aby naprawić to ostrzeżenie, usuń lub zmień nazwę punktu wejścia asynchronicznego.
CS8897 — nie można używać typów statycznych jako parametrów
Fala ostrzegawcza 5
Elementy członkowskie interfejsu nie mogą deklarować parametrów, których typ jest klasą statyczną. Poniższy kod demonstruje zarówno CS8897, jak i CS8898:
public static class Utilities
{
// elided
}
public interface IUtility
{
// CS8897
public void SetUtility(Utilities u);
// CS8898
public Utilities GetUtility();
}
Aby naprawić to ostrzeżenie, zmień typ parametru lub usuń metodę.
CS8898 — typy statyczne nie mogą być używane jako typy zwracane
Fala ostrzegawcza 5
Elementy członkowskie interfejsu nie mogą zadeklarować typu zwracanego, który jest klasą statyczną. Poniższy kod demonstruje zarówno CS8897, jak i CS8898:
public static class Utilities
{
// elided
}
public interface IUtility
{
// CS8897
public void SetUtility(Utilities u);
// CS8898
public Utilities GetUtility();
}
Aby naprawić to ostrzeżenie, zmień typ zwracany lub usuń metodę.