Устранение ошибок и предупреждений для указателей делегатов и функций

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

  • CS0059: Несогласованная доступность: тип параметра 'type' менее доступен, чем делегат 'delegate'.
  • CS0123: Нет перегрузки для 'method', которая соответствует делегату 'delegate'.
  • CS0148: У делегата "делегат" нет корректного конструктора.
  • CS0410: Нет перегрузки для метода с правильными типами параметров и возвращаемого значения.
  • CS0644: "class" не может быть производным от специального класса "class".
  • CS1599: возвращаемый тип метода, делегата или указателя функции не может быть типом.
  • CS1958: Выражение инициализатора объектов и коллекций не может применяться к выражению создания делегата.
  • CS8755: модификатор нельзя использовать в качестве модификатора для параметра указателя функции.
  • CS8756: указатель функции "type" не принимает аргументы count.
  • CS8757: Нет перегрузки для метода, которая соответствует указателю функции 'type'.
  • CS8758: несоответствие ссылок между методом и указателем функции type.
  • CS8759: не удается создать указатель функции для метода, так как он не является статическим методом.
  • CS8786: Соглашение о вызове 'convention' несовместимо с 'convention'.
  • CS8787: не удается преобразовать группу методов в указатель функции. (Нет ли у вас "&"?)
  • CS8788: Не удается использовать метод расширения с приемником в качестве объекта оператора "&".
  • CS8789: тип локального объявленного в фиксированной инструкции не может быть типом указателя функции.
  • CS8806: Соглашение о вызове 'convention' не поддерживается этим языком.
  • CS8807: "описатель" не является допустимым описателем соглашения о вызовах для указателя функции.
  • CS8808: 'Модификатор' не является допустимым модификатором типа возвращаемого указателя функции. Допустимые модификаторы: 'ref' и 'ref readonly'.
  • CS8809: тип возвращаемого значения может иметь только один модификатор с ключевым словом 'modifier'.
  • CS8811: Не удается преобразовать группу методов 'method' в тип делегата 'type'.
  • CS8909: сравнение указателей функций может привести к неожиданному результату, так как указатели на ту же функцию могут отличаться.
  • CS8911: использование типа указателя функции в этом контексте не поддерживается.

Несоответствие подписи делегата

  • CS0059: Несогласованная доступность: тип параметра 'type' менее доступен, чем делегат 'делегат'.
  • CS0123: Нет перегрузки для метода, которая бы соответствовала делегату "делегат".
  • CS0148: делегат "делегат" не имеет допустимого конструктора.
  • CS0410: Ни одна из перегрузок для метода не имеет правильных параметров и возвращаемых типов.

При создании или назначении делегата компилятор проверяет, соответствует ли подпись целевого метода объявлению типа делегата. Подпись включает типы параметров, тип возвращаемого значения и доступность. Полные правила см. в разделе "Делегаты " и "Ограничения специальных возможностей" в спецификации C#.

  • Измените все типы параметров в объявлении делегата на типы, которые по крайней мере доступны как сам делегат (CS0059). Делегат public не может ссылаться на менее доступный тип в списке параметров, так как внешние вызовы вне сборки не смогут предоставить аргумент. Дополнительные сведения см. в разделе "Модификаторы доступа".
  • Измените сигнатуру метода или подпись делегата, чтобы типы параметров и возвращаемый тип соответствовали точно (CS0123). Компилятору требуется точное совпадение подписей при назначении метода делегату.
  • Убедитесь, что делегат компилируется соответствующим компилятором (CS0148). Эта ошибка возникает при импорте управляемой сборки, созданной компилятором, который произвел конструктор делегата с ошибочной структурой. Перекомпилируйте сборку с помощью компилятора, совместимого со стандартами, чтобы устранить ошибку.

Note

CS0410 больше не создается текущим компилятором C#. Это же условие теперь создает CS0123. Старые сборки, скомпилированные с более ранними компиляторами, по-прежнему могут ссылаться на этот код ошибки.

CS0148 — это диагностика, выполняемая только при сборке.

Note

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

Ограничения типа делегата

  • CS0644: "class" не может быть производным от специального класса "class".
  • CS1599: возвращаемый тип метода, делегата или указателя функции не может быть типом.
  • CS1958: выражения инициализатора объектов и коллекции могут не применяться к выражению создания делегата.

Язык C# ограничивает использование определенных специальных типов, включая System.Delegate. Полные правила для объявлений делегатов см. Делегаты и Делегаты в спецификации C#.

  • Удалите явный базовый класс delegate и вместо этого используйте объявление (CS0644). Классы не могут явно наследоваться от System.Delegate, System.EnumSystem.ValueTypeили System.Array. Компилятор использует эти типы в качестве неявных базовых классов. Например, каждое delegate объявление неявно является производным от System.Delegate.
  • Измените возвращаемый тип на тип, разрешенный в качестве возвращаемого значения (CS1599). Некоторые типы в библиотеке классов .NET, такие как TypedReference, RuntimeArgumentHandle и ArgIterator, нельзя использовать в качестве возвращаемых типов для методов, делегатов или указателей функций, так как они могут потенциально включать небезопасные операции стека.
  • Удалите фигурные скобки после выражения создания делегата (CS1958). Делегаты не имеют элементов, которые можно задать с помощью синтаксиса инициализатора объектов или коллекции. Если после выражения new DelegateType(method) у вас есть { }, удалите фигурные скобки.

Несоответствие сигнатуры указателя функции

  • CS8755: модификатор нельзя использовать в качестве модификатора для параметра указателя функции.
  • CS8756: указатель функции "type" не принимает аргументы count.
  • CS8757: Нет перегрузки метода, которая соответствует указателю функции типа 'type'.
  • CS8758: несоответствие ссылок между методом и указателем функции type.
  • CS8759: не удается создать указатель функции для метода, так как он не является статическим методом.
  • CS8787: не удается преобразовать группу методов в указатель функции. (Нет ли у вас "&"?)
  • CS8788: не удается использовать метод расширения с приемником в качестве целевого объекта оператора "&".
  • CS8811: не удается преобразовать группу методов "method" в тип "type".

При назначении метода указателю функции с помощью оператора адреса (&) компилятор проверяет, соответствует ли подпись метода типу указателя функции. Для правил объявления и использования указателей функций см. Указатели функций и Небезопасный код.

  • Удалите неподдерживаемый модификатор из параметра указателя функции (CS8755). Параметры указателя функции поддерживают только модификаторы ref, out и in. Другие модификаторы параметров, такие как params, недопустимы в объявлениях типов указателей функции.
  • Измените количество аргументов на сайте вызова, чтобы соответствовать числу параметров указателя функции (CS8756). Тип указателя функции определяет фиксированное число параметров, и необходимо передать именно столько аргументов.
  • Настройте сигнатуру метода таким образом, чтобы его типы параметров, возвращаемый тип и число параметров соответствовали типу указателя функции (CS8757). В отличие от делегатов, указатели функций не поддерживают неявные преобразования между совместимыми сигнатурами методов. Совпадение должно быть точным.
  • Совместите модификаторы ref, out, или in между параметрами метода и параметрами типа указателя функции (CS8758). Тип ссылки каждого параметра должен точно совпадать. Параметр ref не может удовлетворить in или out позиции в типе указателя функции.
  • Измените целевой метод static на (CS8759). Указатели функций могут указывать только на статические методы, так как они представляют необработанные адреса функций без связанного экземпляра объекта.
  • & Добавьте оператор перед группой методов при назначении указателю функции (CS8787). В отличие от делегатов, указатели функций требуют явного оператора: delegate*<void> ptr = &MyMethod;
  • Используйте статический метод вместо метода расширения с приемником (CS8788). Оператору & требуется ссылка на прямой метод. Методы расширения, вызываемые для экземпляра, имеют неявный приемник, который не может быть записан в указателе функции.
  • Удалите оператор & и используйте синтаксис делегата вместо него, или измените целевой тип с делегата на указатель функции (CS8811). Оператор & создает указатель функции, а не делегат. Чтобы назначить группу методов типу делегата, опустите & и используйте стандартный синтаксис создания делегатов.

Способы вызова указателей на функции и типы возвращаемых значений

  • CS8786: соглашение о вызове соглашения несовместимо с "соглашением".
  • CS8806: Правила вызова 'convention' не поддерживаются этим языком.
  • CS8807: "описатель" не является допустимым описателем соглашения о вызовах для указателя функции.
  • CS8808: «'modifier' не является допустимым модификатором возвращаемого типа указателя функции. Допустимые модификаторы: 'ref' и 'ref readonly'.
  • CS8809: тип возвращаемого значения может иметь только один модификатор.

Объявления указателей функций включают соглашение о вызове и необязательные модификаторы типа возврата. Компилятор проверяет эти параметры. Полные правила см. в указателях функций.

  • Измените соглашение о вызовах метода или соглашение о вызовах типа указателя функции, чтобы они соответствовали (CS8786). При присвоении метода указателю на функцию, соглашение вызова должно быть совместимо. Например, метод, использующий Cdecl , не может быть назначен указателю функции, объявленной с Stdcall.
  • Используйте поддерживаемое соглашение о вызовах в объявлении указателя функции (CS8806). Язык поддерживает managed и unmanaged. Для конкретного соглашения без управления используйте ключевое слово unmanaged с соглашением в квадратных скобках, например, unmanaged[Cdecl], unmanaged[Stdcall], unmanaged[Thiscall] или unmanaged[Fastcall].
  • Замените недопустимый описатель поддерживаемым соглашением о вызовах (CS8807). Используйте managed, unmanagedили unmanaged с типом соглашения о вызове в квадратных скобках (например, unmanaged[Cdecl]).
  • Используйте только модификатор возвращаемого типа ref или ref readonly (CS8808). Другие модификаторы, такие как out или in, не допустимы для типов возвращаемых указателей функций.
  • Удалите повторяющийся модификатор возвращаемого типа, чтобы появился только один ref или ref readonly (CS8809). Компилятор разрешает не более одного модификатора возвращаемого типа в объявлении указателя функции.

Ограничения использования указателя функции

  • CS8789: тип локального объявленного в фиксированной инструкции не может быть типом указателя функции.
  • CS8909: сравнение указателей функций может привести к неожиданному результату, так как указатели на ту же функцию могут отличаться.
  • CS8911: использование типа указателя функции в этом контексте не поддерживается.

Компилятор ограничивает использование типов указателей функций в определенных контекстах. Полные правила см. в указателях функций.

  • Измените тип локальной переменной в fixed инструкции на тип указателя данных вместо типа указателя функции (CS8789). Инструкция fixed закрепляет управляемые объекты в памяти для доступа к данным. Указатели функций представляют адреса кода, а не данные и не могут быть закреплены.
  • Избегайте сравнения указателей функций на равенство (CS8909). Это предупреждение указывает на то, что сравнение указателей функций с == или != может привести к непредвиденным результатам. Среда выполнения может возвращать разные указатели для одной и той же функции из-за деталей реализации, таких как промежуточное представление ("thunking") или JIT-компиляция. Чтобы отключить предупреждение, когда вы подтверждаете, что сравнение намеренно, используйте #pragma warning disable CS8909.
  • Переместите использование указателя функции в поддерживаемый контекст (CS8911). Типы указателей функций не могут использоваться в определенных позициях, таких как аргументы атрибутов или typeof выражения. Переструктурируйте код, чтобы избежать использования типов указателей на функции в неподдерживаемых контекстах.