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


Устраните предупреждения, связанные с using операторами и using объявлениями

В этой статье рассматриваются следующие ошибки компилятора:

  • CS0245: Деструкторы и object.Finalize нельзя вызывать напрямую. При наличии, используйте IDisposable.Dispose.
  • CS0728: Возможно, неправильное присваивание локальной переменной, которая является аргументом для оператора using или lock. Вызов Dispose или разблокировка произойдут на исходном значении локальной переменной.
  • CS1674: тип, используемый в инструкции using, должен быть неявно преобразован в "System.IDisposable".
  • CS8410: "Тип, используемый в асинхронной using инструкции, должен быть неявно преобразован в "System.IAsyncDisposable" или реализовать подходящий метод "DisposeAsync".
  • CS8417: Тип, используемый в асинхронном операторе using, должен реализовать "System.IAsyncDisposable" или реализовать подходящий метод "DisposeAsync". Вы имели в виду "using" вместо "await using"?
  • CS8418: Тип, используемый в инструкции using, должен реализовывать "System.IDisposable". Возможно, вместо 'using' вы имели в виду 'await using'?
  • CS8647: Переменная, объявленная с помощью using, не может быть использована напрямую в разделе оператора switch (рекомендуется использовать фигурные скобки).
  • CS8648: goto невозможно перейти к расположению после объявления using.
  • CS8649: Переход к расположению перед объявлением using в одном блоке невозможно.
  • CS9229: Модификаторы не могут быть применены к директивам using.

Реализация IDisposable и IAsyncDisposable

Следующие ошибки компилятора и предупреждения указывают на проблемы с реализацией или использованием шаблона удаления:

  • CS0245: Деструкторы и object.Finalize не могут быть вызваны напрямую. Если доступно, рассмотрите возможность вызова IDisposable.Dispose.
  • CS1674: тип, используемый в инструкции using, должен быть неявно преобразован в "System.IDisposable".
  • CS8410: тип, используемый в асинхронной using инструкции, должен быть неявно преобразован в "System.IAsyncDisposable" или реализовать подходящий метод DisposeAsync.
  • CS8417: тип, используемый в асинхронной using инструкции, должен реализовать "System.IAsyncDisposable" или реализовать подходящий метод "DisposeAsync". Вы имели в виду "using" а не "await using"?
  • CS8418: Тип, используемый в инструкции using, должен реализовывать "System.IDisposable". Вы имели в виду "await using" вместо "using"?

Оператор using обеспечивает надлежащее удаление ресурсов в конце using блока. Чтобы использовать тип с оператором using , он должен реализовать соответствующий интерфейс удаления. Для синхронных using операторов тип должен реализовать IDisposable. Для асинхронных await using инструкции тип должен реализовать IAsyncDisposable.

  • Нельзя вызвать Finalize напрямую (CS0245): нельзя напрямую вызывать деструктор или метод Object.Finalize. Сборщик мусора автоматически вызывает финализаторы, когда на объекты больше нет ссылок. Для детерминированной очистки реализуйте IDisposable и вызывайте метод Dispose.
  • Тип должен реализовать IDisposable (CS1674): только типы, которые реализуют IDisposable, можно использовать в инструкции using. Типы значений не реализуют этот интерфейс, а параметры универсального типа без соответствующих ограничений не могут быть удалены. Примените ограничение типа, например where T : IDisposable при работе с универсальными типами.
  • Тип должен реализовать IAsyncDisposable (CS8410): Типы, используемые с await using, должны реализовать IAsyncDisposable или предоставить подходящий метод DisposeAsync. Если тип не поддерживает асинхронное удаление, используйте синхронную using инструкцию или реализуйте необходимый интерфейс.
  • Шаблон несогласованного удаления (CS8417, CS8418): CS8417 возникает, когда используется await using с типом, который реализует только IDisposable. CS8418 возникает при использовании синхронного using с типом, который реализует только IAsyncDisposable. Свяжите ключевое слово using с интерфейсом, который реализует ваш тип, или реализуйте оба интерфейса, если требуется поддержка обоих шаблонов.

Дополнительные сведения см. в разделе "Финализаторы", "Реализация метода Dispose" и "Реализация метода DisposeAsync".

Использование переменной области и потока управления

Следующие ошибки компилятора и предупреждения относятся к неправильному using использованию переменных в инструкциях потока управления:

  • CS0728: возможно, неправильное присвоение локальной переменной, которая является аргументом для оператора using или lock. Вызов функции Dispose или разблокировка будет происходить с исходным значением локальной переменной.
  • CS8647: переменная типа using не может быть использована напрямую внутри секции оператора switch (рекомендуется использовать фигурные скобки).
  • CS8648: goto не может перейти на участок кода после объявления using.
  • CS8649: Невозможно перейти к месту перед объявлением using в пределах одного блока.

Переменные, объявленные с помощью using, имеют специфические правила области видимости, которые предотвращают утечку ресурсов. Компилятор применяет эти правила, чтобы обеспечить надлежащее удаление.

  • Назначение использования переменной (CS0728): это предупреждение указывает, что вы присвоили новое значение переменной, которая используется как ресурс в инструкции using . Вызов dispose происходит на оригинальном значении, а не на новому назначенному значению, что может привести к утечкам ресурсов. Инициализируйте ресурс в using объявлении оператора вместо позднего присваивания.

  • Использование переменной в разделе switch (CS8647): using объявление создает переменную, которая удаляется в конце своей области видимости. При использовании непосредственно в разделе переключателя в отсутствии фигурных скобок область видимости становится неоднозначной и может привести к ошибкам. Заключите содержимое раздела переключателя в фигурные скобки, чтобы четко определить область.

  • Операторы Goto и объявления с использованием (CS8648, CS8649) нельзя использовать goto инструкции для перехода к using объявлениям, так как переход будет пропускать надлежащее управление ресурсами. CS8648 возникает при переходе вперед через объявление using, а CS8649 происходит при возврате к месту до объявления using. Переструктурируйте код, чтобы использовать структурированный поток управления, например циклы, или переместить using объявление за пределы целевого объекта перехода.

Дополнительные сведения см. в инструкции using.

Неправильное using объявление

  • CS9229: Модификаторы не могут быть помещены на using-директивы.

Объявление переменной, упаковаемое в using объявление, не может содержать ни одного из следующих модификаторов:

  • const
  • static
  • volatile
  • readonly
  • Модификаторы специальных возможностей: public, protected, , internalprivateили protected internalprivate protected

В следующем примере генерируется ошибка CS9229:

using System;

class Program
{
    static void Main()
    {
        // error CS9229: Modifiers cannot be placed on using declarations.
        public using var resource = new Resource();
        
        // error CS9229: Modifiers cannot be placed on using declarations.
        static using var anotherResource = new Resource();
    }
}

class Resource : IDisposable
{
    public void Dispose() { }
}

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

using var resource = new Resource();

Дополнительные сведения см. в инструкции using.