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


Ошибки и предупреждения при использовании лямбда-выражений и анонимных функций

Некоторые ошибки связаны с объявлением и использованием лямбда-выражений и анонимных методов:

  • CS0407: метод имеет неправильный тип возвращаемого значения.
  • CS0428: не удается преобразовать группу методов "Идентификатор" в тип "type", отличный от делегата. Вы намеревались вызвать метод?
  • CS0748: несогласованное использование лямбда-параметра; типы параметров должны быть явными или неявными.
  • CS0815: не удается назначить выражение неявно типизированной переменной.
  • CS0828: не удается назначить выражение свойству анонимного типа.
  • CS0837: первый операнд оператора is или as не может быть лямбда-выражением, анонимным методом или группой методов.
  • CS1065: значения по умолчанию недопустимы в этом контексте.
  • CS1621: Оператор yield не может использоваться внутри анонимного метода или лямбда-выражения.
  • CS1628: не удается использовать inref или out параметр внутри анонимного метода, лямбда-выражения или выражения запроса.
  • CS1632: управление не может покинуть тело анонимного метода или лямбда-выражения.
  • CS1643: не все пути кода возвращают значение в анонимном методе типа "type".
  • CS1660: не удается преобразовать лямбда-выражение в тип "type", так как он не является типом делегата.
  • CS1661: не удается преобразовать блок анонимного метода в тип "type", так как типы параметров не соответствуют типам параметров делегата.
  • CS1662: невозможно преобразовать блок анонимного метода в предполагаемый тип делегата, поскольку некоторые типы возвращаемых значений в блоке не могут быть неявно преобразованы в тип возвращаемого значения делегата.
  • CS1673: анонимные методы, лямбда-выражения и выражения запросов в структурах не могут получить доступ к членам экземпляра this.
  • CS1676: параметр "number" должен быть объявлен с ключевым словом "keyword".
  • CS1677: параметр "number" не должен быть объявлен с ключевым словом "keyword".
  • CS1678: параметр "number" объявлен как тип "type1", но должен иметь тип 2.
  • CS1686: локальная переменная или ее члены не могут принимать свой адрес и использоваться внутри анонимного метода или лямбда-выражения.
  • CS1688: не удается преобразовать блок анонимного метода без списка параметров в делегат типа 'delegate', так как он имеет один или несколько выходных параметров.
  • CS1706: выражение не может содержать анонимные методы или лямбда-выражения.
  • CS1731: Невозможно преобразовать выражение в делегат, поскольку некоторые из возвращаемых типов в блоке не могут быть неявно преобразованы в возвращаемый тип делегата.
  • CS1732: ожидаемый параметр.
  • CS1764: не удается использовать фиксированный локальный код в анонимном методе, лямбда-выражении или выражении запроса.
  • CS8030: Анонимная функция, преобразованная в делегат, возвращающий void, не может возвращать значение.
  • CS8175: не удается использовать ref local внутри анонимного метода, лямбда-выражения или выражения запроса.
  • CS8820: Статическая анонимная функция не может содержать ссылку на 'переменную'.
  • CS8821: Статическая анонимная функция не может содержать ссылку на "this" или "base".
  • CS8916: атрибуты для лямбда-выражений требуют списка параметров с скобками.
  • CS8917: тип делегата не может быть выведен.
  • CS8934: не удается преобразовать анонимный метод в тип "type", так как возвращаемый тип не соответствует типу возвращаемого делегата.
  • CS8975: контекстное ключевое слово var нельзя использовать в качестве явного лямбда-возвращаемого типа.
  • CS9098: неявно типизированный лямбда-параметр "..." не может иметь значение по умолчанию.

Кроме того, несколько предупреждений связаны с объявлением и использованием лямбда-выражений:

  • CS0467: Неоднозначность между методом "method" и неметодом "non-method". Применение группы методов.
  • CS1911: доступ к члену через ключевое слово base из анонимного метода, лямбда-выражения, выражения запроса или итератора приводит к непроверяемому коду.
  • CS8971: InterpolatedStringHandlerArgument не действует при применении к лямбда-параметрам и будет игнорироваться в точке вызова.
  • CS8974: Преобразование группы методов "method" в тип, не являющийся делегатом "type". Хотели ли вы вызвать метод?
  • CS9099: значение параметра по умолчанию не совпадает в целевом типе делегата.
  • CS9100: параметр имеет модификатор 'params' в лямбда-выражении, но не в целевом типе функции-делегата.

Компилятор также создает следующее информационное сообщение:

  • CS9236: компиляция требует привязки лямбда-выражения по крайней мере количества раз. Рассмотрите возможность объявления лямбда-выражения с явными типами параметров или если вызов содержащего метода является универсальным, рассмотрите возможность использования явных аргументов типа.

Ограничения синтаксиса в лямбда-выражениях

  • CS0837: первый операнд оператора is или as не может быть лямбда-выражением, анонимным методом или группой методов.
  • CS1621: yield оператор нельзя использовать внутри анонимного метода или лямбда-выражения.
  • CS1628: не удается использовать inили refoutпараметр внутри анонимного метода, лямбда-выражения или выражения запроса.
  • CS1632: элемент управления не может оставить текст анонимного метода или лямбда-выражения.
  • CS1673: анонимные методы, лямбда-выражения и выражения запросов внутри структур не могут получить доступ к членам экземпляра this.
  • CS1686: локальная переменная или ее члены не могут принимать свой адрес и использоваться внутри анонимного метода или лямбда-выражения.
  • CS1706: выражение не может содержать анонимные методы или лямбда-выражения.
  • CS1764: не удается использовать фиксированный локальный код в анонимном методе, лямбда-выражении или выражении запроса.
  • CS1911: Предупреждение: доступ к члену через ключевое слово 'base' из анонимного метода, лямбда-выражения, выражения запроса или итератора приводит к непроверяемому коду.
  • CS8175: не удается использовать ref local внутри анонимного метода, лямбда-выражения или выражения запроса.
  • CS8820: Статическая анонимная функция не может содержать ссылку на 'переменную'.
  • CS8821: Статическая анонимная функция не может содержать ссылки на "this" или "base".
  • CS8971: Предупреждение: InterpolatedStringHandlerArgument не действует при применении к лямбда-параметрам и будет игнорироваться в месте вызова.
  • CS9236: Информационный: компиляция требует привязки лямбда-выражения по крайней мере несколько раз. Рассмотрите возможность объявления лямбда-выражения с явно заданными типами параметров или если вызов содержащего метода является универсальным, рассмотрите возможность использования явно заданных аргументов типа.

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

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

  • Переместите любое выражение yield return или yield break из тела лямбда в обрамляющий метод итератора или преобразуйте лямбда-выражение в локальную функцию, которая поддерживает инструкции yield (CS1621).
  • Избегайте ссылок на параметры in, ref, или out из окружающего метода внутри тела лямбда-выражения. Когда лямбда фиксирует эти параметры как часть замыкания, ссылочная семантика ref-подобных параметров не может быть сохранена. Скопируйте значение в локальную переменную, затем используйте эту переменную или преобразуйте лямбда-выражение в локальную функцию (CS1628).
  • Удалите любой оператор break, goto или continue, который передает контроль из лямбда-выражения. Инструкции потока управления должны указывать на метки или циклы в одном лямбда-тексте (CS1632).
  • В типе struct не следует ссылаться на экземплярные члены this внутри лямбда-выражения, анонимного метода или выражения запроса. Поскольку компилятор захватывает this по значению в лямбда-выражении, изменения внутри лямбда-функции не влияют на исходный экземпляр. Извлеките необходимые значения членов в локальные переменные перед лямбда-выражением или преобразуйте его в локальную функцию, которая может получить прямой доступ к this (CS1673).
  • Не берите адрес локальной переменной, которую лямбда-функция также захватывает. Компилятор перемещает захваченные переменные в объект замыкания, размещённый в куче, тем самым делая их адрес неустойчивым. Отделите логику принятия адресов от лямбда-кода или используйте локальную функцию (CS1686).
  • Переместите лямбда-выражение или анонимный метод из содержащего выражения, запрещающего его. Некоторые выражения, такие как конструкторы атрибутов, не поддерживают лямбда-выражения или анонимные методы в качестве аргументов (CS1706).
  • Не используйте локальную fixed переменную внутри лямбда-тела. Гарантия закрепления инструкцииfixed применяется только к заключающей области, а не к закрытию, которое создает компилятор (CS1764).
  • Не используйте локальныйref внутри лямбда-тела. Как и ref параметры, ref локальные переменные не могут быть захвачены в замыкании, которое компилятор генерирует для лямбда-функции. Назначьте значение нелокальнойref переменной или преобразуйте лямбда-выражение в локальную функцию (CS8175).
  • Не используйте лямбда-выражение, анонимный метод или группу методов в качестве первого операнда is оператора или as оператора. Эти конструкции не имеют типа, который можно проверить во время выполнения. Сначала назначьте выражение переменной, а затем проверьте переменную (CS0837).
  • static Удалите модификатор из лямбда-файла или удалите ссылку на захваченную переменную. static Лямбда явно запрещает захват локальных переменных, параметров или this, чтобы избежать непреднамеренных выделений для замыкания. Если вам нужно ссылаться на внешние переменные, удалите static модификатор. Если вы хотите сохранить минимальное выделение кучи, передайте значения в лямбда-параметры (CS8820, CS8821).
  • Удалите InterpolatedStringHandlerArgumentAttribute из параметра лямбда-выражения или переместите код в метод, где этот атрибут учитывается. Компилятор игнорирует этот атрибут для лямбда-параметров, так как лямбда-вызовы не используют ту же процедуру понижения обработчика интерполированных строк, что и обычные вызовы методов (CS8971).
  • Избегайте вызова виртуального члена с помощью ключевого слова base внутри лямбда-выражения или анонимного метода. Компилятор создает неиртуативный вызов с помощью вспомогательного метода, который создает непроверяемый код. Рассмотрите возможность вынесения вызова base в отдельный метод и вызова этого метода из лямбда-выражения (CS1911).
  • Уменьшите сложность перегруженных вызовов методов, которые принимают лямбда-выражения или добавляют явные сведения о типе. Когда компилятор должен привязать лямбда-выражение несколько раз для разрешения перегрузки, он выдает эту информационную диагностику. Объявление лямбда-выражения с явными типами параметров или предоставление явных аргументов типа в вызове универсального метода уменьшает количество операций связывания, которые должен выполнять компилятор (CS9236).

Параметры лямбда-выражения и возвращаемое значение

  • CS0748: несогласованное использование лямбда-параметра; типы параметров должны быть явными или неявными.
  • CS1065: значения по умолчанию недопустимы в этом контексте.
  • CS1643: не все пути кода возвращают значение в анонимном методе типа "type".
  • CS1661: не удается преобразовать блок анонимного метода в тип "type", так как типы параметров не соответствуют типам параметров делегата.
  • CS1662: невозможно преобразовать блок анонимного метода в предполагаемый тип делегата, так как некоторые типы возвращаемых данных в блоке неявно не преобразуются в тип возвращаемого делегата.
  • CS1676: параметр "number" должен быть объявлен с ключевым словом "keyword".
  • CS1677: параметр "number" не должен быть объявлен с ключевым словом "keyword".
  • CS1678: параметр "number" объявлен как тип "type1", но должен иметь тип 2.
  • CS1688: не удается преобразовать блок анонимного метода без списка параметров в тип делегата, так как он содержит один или несколько выходных параметров.
  • CS1731: невозможно преобразовать выражение в делегат, так как некоторые возвращаемые типы в блоке неявно не преобразуются в тип возвращаемого значения делегата.
  • CS1732: ожидаемый параметр.
  • CS8030: Анонимная функция, преобразованная в делегат, не возвращающий значение, не может возвращать значение.
  • CS8916: атрибуты для лямбда-выражений требуют списка параметров с скобками.
  • CS8934: не удается преобразовать анонимный метод в тип "type", так как возвращаемый тип не соответствует типу возвращаемого делегата.
  • CS8975: контекстное ключевое слово var нельзя использовать в качестве явного лямбда-возвращаемого типа.
  • CS9098: неявно типизированный лямбда-параметр "..." не может иметь значение по умолчанию.

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

Замечание

CS1731 и CS1732 больше не создаются текущей версией компилятора C# (Roslyn). Они могут отображаться, если вы используете старую версию компилятора.

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

  • Убедитесь, что все параметры в лямбда-выражении используют одинаковый стиль ввода. Если лямбда-файл имеет несколько параметров, каждый параметр должен быть явно типизированным или неявно типизированным — нельзя смешивать два стиля в одном списке параметров (CS0748).
  • Добавьте явные типы в любой лямбда-параметр, имеющий значение по умолчанию. Компилятору требуются явные типы параметров с параметрами по умолчанию, так как он должен создать пользовательский тип делегата, который кодирует значение по умолчанию. Неявно типизированные параметры не предоставляют достаточно сведений для компилятора, чтобы создать этот тип делегата (CS1065, CS9098).
  • Удалите значения параметров по умолчанию из анонимных методов, объявленных с помощью delegate оператора. Значения параметров по умолчанию поддерживаются только в лямбда-выражениях, а не в анонимных методах. Преобразуйте анонимный метод в лямбда-выражение, если вам нужны значения по умолчанию (CS1065).
  • Соответствует типам параметров, ref/out/inмодификаторам и числу параметров лямбда-метода или анонимного типа целевого делегата. Компилятор выполняет точное совпадение подписей параметров при преобразовании анонимной функции в делегат: каждый параметр должен иметь правильный тип, а любой ref, out, или in модификатор должен присутствовать точно тогда, когда это ожидается делегатом (CS1661, CS1676, CS1677, CS1678).
  • Добавьте список параметров в анонимный метод, если целевой тип делегата имеет out параметры. Анонимный метод, объявленный без списка параметров (с помощью delegate { } синтаксиса), может соответствовать большинству типов делегатов, но компилятор не может синтезировать необходимые out параметры неявно. Объявите параметры явным образом, чтобы соответствовать подписи делегата (CS1688).
  • Убедитесь, что все пути кода в лямбда-или анонимном методе возвращают значение, если тип целевого делегата имеет тип возвращаемого значения, отличного от void. Каждая ветвь в теле должна возвращать значение, которое неявно преобразуемо в тип возвращаемого значения делегата (CS1643, CS1662, CS1731, CS8934).
  • Удалите любую return инструкцию со значением из лямбда-выражения или анонимного метода, присвоенного типу делегата, возвращающему void, например Action. Поскольку возвращаемый тип делегата является void, тело не может возвращать значение (CS8030).
  • Заключите список параметров в скобки, когда атрибуты применяются к любому лямбда-параметру. Компилятору нужна форма в круглых скобках, чтобы различать синтаксис атрибутов от других выражений. Например, запись ([MyAttribute] int x) => x вместо [MyAttribute] x => x(CS8916).
  • Используйте имя определенного типа вместо var как явного возвращаемого типа лямбда-выражения. Ключевое слово var зарезервировано для неявно типизированных локальных переменных и не может использоваться в качестве заметки лямбда-возвращаемого типа. Укажите фактический тип возвращаемого значения или опустите возвращаемый тип и позволить компилятору определить его (CS8975).
  • Исправьте список параметров, чтобы компилятор смог распознать его как допустимое объявление параметров. Эта ошибка указывает на неправильный список параметров, в котором компилятор ожидал идентификатор параметра, но нашел что-то другое (CS1732).

Тип делегата лямбда-выражения

  • CS0407: метод имеет неправильный тип возвращаемого значения.
  • CS0428: не удается преобразовать группу методов "Идентификатор" в тип "type", отличный от делегата. Вы намеревались вызвать метод?
  • CS0467: Предупреждение: Неоднозначность между методом "method" и неметодом "non-method". Будет использоваться группа методов.
  • CS0815: не удается назначить выражение неявно типизированной переменной.
  • CS0828: не удается назначить выражение свойству анонимного типа.
  • CS1660: не удается преобразовать лямбда-выражение в тип "type", так как он не является типом делегата.
  • CS8917: тип делегата не может быть выведен.
  • CS8974: предупреждение: преобразование группы методов 'method' в тип 'type', который не является делегатом. Вы имели в виду вызвать метод?
  • CS9099: предупреждение: значение параметра по умолчанию не соответствует типу целевого делегата.
  • CS9100: Предупреждение: параметр имеет модификатор params в лямбда-выражении, но не в целевом типе делегирования.

Эти ошибки указывают на проблему с типом делегата , который компилятор вводит или ожидает для лямбда-выражения, анонимного метода или группы методов. Полные правила преобразования делегатов см. в лямбда-выражениях, анонимных методах и анонимных выражениях функций спецификации C#.

Замечание

Текущая версия компилятора C# (Roslyn) не создает CS0467. Эта ошибка может появиться, если вы используете старую версию компилятора.

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

  • Убедитесь, что целевой тип назначения или преобразования является типом делегата или System.Linq.Expressions.Expression. Лямбда-выражение или анонимный метод нельзя назначить типу, который не является делегатом, например, object или интерфейсу. Измените тип переменной на совместимый тип делегата, например Func<> или Action<>используйте var , чтобы компилятор выводил тип делегата (CS1660).
  • Укажите достаточно контекста для компилятора, чтобы определить один тип делегата для лямбда-выражения. При назначении varкомпилятору требуется однозначно возвращаемый тип и список параметров. Когда назначают свойство анонимного типа, компилятор вообще не может вывести тип делегата. Назначьте лямбда-переменную переменной с явным типом делегата, а затем используйте эту переменную в инициализаторе анонимного типа (CS0815, CS0828, CS8917).
  • Тип возвращаемого значения группы методов должен соответствовать объявленному типу возвращаемого значения делегата. Преобразование группы методов требует, чтобы возвращаемый тип метода был идентичным или неявно преобразуемым в возвращаемый тип делегата. Измените тип возвращаемого метода или измените тип делегата на соответствие (CS0407).
  • Вызовите метод вместо назначения группы методов, если целевой тип не является делегатом. Если целевой тип — это string, int или какой-либо другой тип, отличный от делегата, скорее всего, вы намерены вызвать метод и присвоить его результат. Добавьте скобки и аргументы для вызова метода (CS0428, CS8974).
  • Устраните неоднозначность между методом и членом, не использующего одно и то же имя. Переименуйте один из конфликтующих членов или используйте полную ссылку для удаления неоднозначности (CS0467).
  • Удалите значение параметра по умолчанию или params модификатор из лямбда,если целевой тип делегата является стандартным Func<> или Action<> типом. Значения по умолчанию и params модификаторы вызывают создание пользовательского типа делегата, который не соответствует Func<> или Action<>. Используйте var, чтобы компилятор синтезировал правильный тип делегата, или удалите значение по умолчанию или модификатор params, чтобы лямбда соответствовала объявленному типу делегата (CS9099, CS9100).