Поделиться через


Волны предупреждений C#

Новые предупреждения и ошибки можно ввести в каждом выпуске компилятора C#. Когда новые предупреждения могут быть сообщены о существующем коде, эти предупреждения вводятся в системе согласия, называемой волной предупреждений. Система согласия означает, что вы не должны видеть новые предупреждения в существующем коде, не выполняя действия, чтобы включить их. Волны предупреждений включены с помощью элемента AnalysisLevel в файле проекта. Если <TreatWarningsAsErrors>true</TreatWarningsAsErrors> задано, включено предупреждение волны предупреждений создает ошибки. Предупреждение 5 диагностика было добавлено в C# 9. Предупреждение 6 диагностика добавлено в C# 10. Предупреждение 7 диагностика добавлено в C# 11. Предупреждение 8 диагностика было добавлено в C# 12.

CS9123 — получение адреса локального или параметра в асинхронном методе может создать отверстие GC.

Предупреждающие волны 8

Оператор & не должен использоваться для параметров или локальных переменных в асинхронных методах. Следующий код создает CS9123:

public static async Task LogValue()
{
    int x = 1;
    unsafe {
        int* y = &x;
        Console.WriteLine(*y);
    }
    await Task.Delay(1000);
}

Начиная с C# 13, этот код создает ошибку компилятора.

CS8981 — имя типа содержит только символы ascii нижнего регистра.

Предупреждающие волны 7

Все новые ключевые слова, добавленные для C#, будут все символы ASCII нижнего регистра. Это предупреждение гарантирует, что ни один из типов не конфликтует с будущими ключевыми словами. Следующий код создает CS8981:

public class lowercasename
{
}

Это предупреждение можно устранить, переименовав тип, чтобы включить по крайней мере один символ ASCII, отличный от нижнего регистра, например верхний регистр, цифру или символ подчеркивания.

CS8826 — объявления частичных методов имеют различия между сигнатурами.

Предупреждающие волны 6

Это предупреждение исправляет некоторые несоответствия в отчетах между сигнатурами частичных методов. Компилятор всегда сообщал об ошибке, когда сигнатуры частичных методов создали разные подписи СРЕДЫ CLR. Теперь компилятор сообщает CS8826, когда подписи синтаксически отличаются от C#. Рассмотрим следующий частичный класс:

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);
}

Следующая реализация частичного класса создает несколько примеров 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) { }
}

Примечание.

Если реализация метода использует ненулевой ссылочный тип, если другое объявление принимает ссылочные типы, допускающие значение NULL, создается CS8611 вместо CS8826.

Чтобы исправить любой экземпляр этих предупреждений, убедитесь, что две сигнатуры соответствуют.

CS7023 — статический тип используется в выражении is или as.

Предупреждающие волны 5

as Выражения is всегда возвращаются false для статического типа, так как нельзя создавать экземпляры статического типа. Следующий код создает 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");
    }
}

Компилятор сообщает об этом предупреждении, так как тест типа не может завершиться успешно. Чтобы исправить это предупреждение, удалите тест и удалите любой код, выполняемый только в случае успешного выполнения теста. В предыдущем примере else предложение всегда выполняется. Этот текст метода можно заменить одной строкой:

Console.WriteLine("o is not an instance of a static class");

CS8073 — результат выражения всегда имеет значение false (или true).

Предупреждающие волны 5

Операторы == всегда возвращают false (илиtrue) при сравнении экземпляра struct типа с null.!= В следующем коде показано это предупреждение. ПредположимS, что определяется operator == struct и 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...
}

Чтобы устранить эту ошибку, удалите проверку null и код, который будет выполняться, если объект имеет значение null.

CS8848 — оператор from не может использоваться здесь из-за приоритета. Используйте скобки для диамбигуации.

Предупреждающие волны 5

В следующих примерах показано это предупреждение. Выражение привязывается неправильно из-за приоритета операторов.

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];

Чтобы устранить эту ошибку, поместите круглые скобки вокруг выражения запроса:

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)];

Члены должны быть полностью назначены. Использование неназначенных переменных (CS8880, CS8881, CS8882, CS8883, CS8884, CS8885, CS886, CS8887)

Предупреждающие волны 5

Несколько предупреждений улучшают определенный анализ назначений для типов, struct объявленных в импортированных сборках. Все эти новые предупреждения создаются, когда структура импортированной сборки включает недоступное поле (обычно private поле) ссылочного типа, как показано в следующем примере:

public struct Struct
{
    private string data = String.Empty;
    public Struct() { }
}

В следующих примерах показаны предупреждения, созданные из улучшенного анализа определенного назначения:

  • CS8880: автоматически реализованное свойство Property должно быть полностью назначено перед возвратом элемента управления вызывающему объекту.
  • CS8881: поле "поле" должно быть полностью назначено перед возвратом элемента управления вызывающему объекту.
  • CS8882: параметр out должен быть назначен перед выходом элемента управления из текущего метода.
  • CS8883: использование, возможно, неназначенных автоматически реализованных свойств "Property".
  • CS8884: использование, возможно, неназначаемого поля "Поле"
  • CS8885: объект "этот" нельзя использовать до назначения всех его полей.
  • CS8886: использование неназначенных выходных параметров "parameterName".
  • CS8887: использование неназначенных локальных переменных "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;
    }
}

Вы можете исправить любое из этих предупреждений, инициализировав или назначив импортированную структуру его значению по умолчанию:

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 — метод не будет использоваться в качестве точки входа, так как найдена синхронная точка входа method.

Предупреждающие волны 5

Это предупреждение создается для всех кандидатов асинхронной точки входа при наличии нескольких допустимых точек входа, включая одну или несколько синхронных точек входа.

В следующем примере возникает ошибка CS8892:

public static void Main()
{
    RunProgram();
}

// CS8892
public static async Task Main(string[] args)
{
    await RunProgramAsync();
}

Примечание.

Компилятор всегда использует синхронную точку входа. Если существует несколько синхронных точек входа, возникает ошибка компилятора.

Чтобы устранить это предупреждение, удалите или переименуйте асинхронную точку входа.

CS8897 — статические типы не могут использоваться в качестве параметров

Предупреждающие волны 5

Члены интерфейса не могут объявлять параметры, тип которых является статическим классом. Следующий код демонстрирует как CS8897, так и CS8898:

public static class Utilities
{
    // elided
}

public interface IUtility
{
    // CS8897
    public void SetUtility(Utilities u);

    // CS8898
    public Utilities GetUtility();
}

Чтобы устранить это предупреждение, измените тип параметра или удалите метод.

CS8898 — статические типы нельзя использовать в качестве возвращаемых типов

Предупреждающие волны 5

Члены интерфейса не могут объявлять тип возвращаемого значения, который является статическим классом. Следующий код демонстрирует как CS8897, так и CS8898:

public static class Utilities
{
    // elided
}

public interface IUtility
{
    // CS8897
    public void SetUtility(Utilities u);

    // CS8898
    public Utilities GetUtility();
}

Чтобы устранить это предупреждение, измените возвращаемый тип или удалите метод.