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


Ошибки и предупреждения, связанные с эталонными параметрами, переменными и возвратами

При работе с ссылочными переменными могут возникать следующие ошибки:

  • CS0192: readonly поле нельзя использовать как значение ref или out значение (за исключением конструктора)
  • CS0199: static readonly поле нельзя использовать как ref значение или out значение (за исключением статического конструктора)
  • CS0206: свойство или индексатор не ref-returning могут использоваться в качестве out значения или ref значения.
  • CS0631: ref и out недопустимы в этом контексте
  • CS0767: не удается наследовать интерфейс с указанными параметрами типа, так как он приводит к тому, что метод содержит перегрузки, которые отличаются только от ref и out
  • CS1510: переменная ref или out значение должна быть назначаемой переменной.
  • CS1605: не удается использовать переменную в качестве ref значения или out значения, так как она доступна только для чтения
  • CS1623: не удается иметь refinитераторы или out параметры
  • CS1649: элементы readonly поля нельзя использовать как ref или out значение (за исключением конструктора)
  • CS1651: поля статического поля чтения нельзя использовать как ref или out значение (за исключением статического конструктора)
  • CS1655: не удается использовать поля типа в качестве ref или out значения
  • CS1657: не удается использовать переменную в ref качестве значения или out значения
  • CS1741: значение ref по умолчанию или out параметр не может иметь значение по умолчанию
  • CS1939: не удается передать переменную диапазона в качестве out или ref параметра
  • CS1988: не удается иметь refin асинхронные методы или out параметры
  • CS7084: событие среда выполнения Windows может не передаваться в виде out или ref параметра.
  • CS8196: ссылка на неявную типизированные переменную не допускается в том же списке аргументов.
  • CS8325: 'await' нельзя использовать в выражении, содержам условный ref оператор
  • CS8326: оба значения условных операторов должны быть ссылочные или не могут быть ссылочные значения
  • CS8327: выражение должно иметь правильный тип, чтобы соответствовать альтернативному значению ссылок
  • CS8329: не удается использовать переменную в качестве ref значения или out значения, так как это переменная для чтения
  • CS8330: элементы переменной нельзя использовать в качестве ref значения или out значения, так как это переменная для чтения
  • CS8331: не удается назначить переменную или использовать ее в качестве правой стороны ref назначения, так как это переменная считывания
  • CS8332: не удается назначить элемент переменной или использовать его в качестве правой стороны ref назначения, так как это переменная считывания
  • CS8337: первый параметр метода расширения "ref" должен быть типом значения или универсальным типом, ограниченным структурой.
  • CS8338: первый параметр "" илиin "ref readonly" метода расширения должен быть конкретным (не универсальным) типом значения.
  • CS8373: левая сторона ref назначения должна быть переменной ссылок.
  • CS8388: out переменная не может быть объявлена как локальная ссылка
  • CS8977: не удается использовать '', 'refin' или 'out' в сигнатуре метода с атрибутом UnmanagedCallersOnly.
  • CS8986: модификатор "scoped" параметра не соответствует целевому объекту.
  • CS8987: модификатор "scoped" параметра не совпадает с переопределенным или реализованным элементом.
  • CS9061: модификатор scoped нельзя использовать с выбросом.
  • CS9062: Типы и псевдонимы не могут называться 'scoped'.
  • CS9063: UnscopedRefAttribute не может быть применен к этому параметру, потому что он по умолчанию не имеет области действия.
  • CS9065: не используйте System.Runtime.CompilerServices.ScopedRefAttribute. Вместо этого используйте ключевое слово scoped.
  • CS9066: unscopedRefAttribute нельзя применить к параметрам, имеющим модификатор "scoped".
  • CS9072: переменная деконструкции не может быть объявлена как локальная ссылка
  • CS9101: UnscopedRefAttribute может применяться только к методам и свойствам экземпляра структуры или виртуального интерфейса и не может применяться к конструкторам или элементам только для инициализации.
  • CS9102: не удается применить unscopedRefAttribute к реализации интерфейса, так как реализованный член не имеет этого атрибута.
  • CS9104: using ресурс оператора типа нельзя использовать в асинхронных методах или асинхронных лямбда-выражениях.
  • CS9190: readonly модификатор должен быть указан после ref.
  • CS9199: ref readonly параметр не может иметь атрибут Out.

При неправильном использовании ссылочных переменных создаются следующие предупреждения:

  • CS9073: модификатор "scoped" параметра не соответствует целевому объекту.
  • CS9074: модификатор "scoped" параметра не совпадает с переопределенным или реализованным элементом.
  • CS9191: ref модификатор аргумента, соответствующего параметруin, эквивалентенin. Вместо этого рекомендуется использоватьin.
  • CS9192: аргумент должен передаваться с ключевым словом ref или in ключевым словом.
  • CS9193: аргумент должен быть переменной, так как он передается параметру ref readonly .
  • CS9195: аргумент должен передаваться с ключевым словом in
  • CS9196: модификатор типа ссылок параметра не соответствует соответствующему параметру в переопределенном или реализованном элементе.
  • CS9197: модификатор типа ссылок параметра не соответствует соответствующему параметру в скрытом элементе.
  • CS9198: модификатор типа ссылок параметра не соответствует соответствующему параметру в целевом объекте.
  • CS9200: значение по умолчанию указано для ref readonly параметра, но ref readonly должно использоваться только для ссылок. Рассмотрите возможность объявления параметра как in.
  • CS9201: поле ref следует назначить ref перед использованием.
  • CS9265: поле никогда не назначается ссылочным, и всегда будет иметь значение по умолчанию (ссылка null)

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

В этой статье используется переменная ссылки на термин в качестве общего термина для параметра, объявленного с одним из inмодификаторов, ref readonlyrefили out локальных переменныхref, ref поля в ref structполе или возвращаемого ref значения. Ссылочная переменная ссылается на другую переменную, называемую ссылочной.

Неверный синтаксис

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

  • CS8373: левая сторона ref назначения должна быть переменной ссылок.
  • CS8388: out переменная не может быть объявлена как локальная ссылка.
  • CS9190: readonly модификатор должен быть указан после ref.

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

  • Убедитесь, что левый операнд = ref оператора является ссылочной переменной, а не значением выражения или не-ссылочной локальной переменной. Назначение ссылок требует, чтобы обе стороны ссылались на переменные, которые могут создавать псевдоним в одном расположении хранилища (CS8373).
  • При объявлении ссылочных параметров используйте модификатор ref readonly, а не readonly ref. Спецификация языка C# требует, чтобы ключевое слово ref предшествовало модификатору readonly в объявлениях параметров для поддержания согласованного синтаксиса во всех ссылочных типах параметров (CS9190).
  • Используйте ключевое слово ref вместо out при объявлении локальных ссылочных переменных. out является исключительно модификатором параметров, указывающим, что метод должен назначить значение перед возвратом, в то время как ref является соответствующим ключевым словом для создания локальных переменных, которые псевдонимируют другие расположения хранилища (CS8388). Дополнительные сведения о ссылочных переменных и их требованиях к синтаксису см. в справочных переменных и спецификации языка C#.

Ограничения ссылочных переменных

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

  • CS0631: ref и out недопустимы в этом контексте
  • CS0767: не удается наследовать интерфейс с указанными параметрами типа, так как он приводит к тому, что метод содержит перегрузки, которые отличаются только от ref и out
  • CS1623: не удается иметь refin итераторы или out параметры
  • CS1741: значение ref по умолчанию или out параметр не может иметь значение по умолчанию
  • CS1939: не удается передать переменную диапазона в качестве out или ref параметра
  • CS1988: не удается иметь refin асинхронные методы или out параметры
  • CS7084: событие среда выполнения Windows может не передаваться в виде out или ref параметра.
  • CS8196: ссылка на неявную переменную типа out не допускается в том же списке аргументов.
  • CS8325: "await" не может использоваться в выражении, содержаемом условным оператором ref
  • CS8326: оба значения условных операторов должны быть ссылочные или не могут быть ссылочные значения
  • CS8327: выражение должно иметь правильный тип, чтобы соответствовать альтернативному значению ссылок
  • CS8337: первый параметр метода расширения "ref" должен быть типом значения или универсальным типом, ограниченным структурой.
  • CS8338: первый параметр "" илиin "ref readonly" метода расширения должен быть конкретным (не универсальным) типом значения.
  • CS8977: не удается использовать '', 'refin' или 'out' в сигнатуре метода с атрибутом UnmanagedCallersOnly.
  • CS9072: переменная деконструкции не может быть объявлена как локальная ссылка
  • CS9104: using ресурс оператора типа нельзя использовать в асинхронных методах или асинхронных лямбда-выражениях.
  • CS9199: ref readonly параметр не может иметь атрибут Out.

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

  • CS9196: модификатор типа ссылок параметра не соответствует соответствующему параметру в переопределенном или реализованном элементе.
  • CS9197: модификатор типа ссылок параметра не соответствует соответствующему параметру в скрытом элементе.
  • CS9198: модификатор типа ссылок параметра не соответствует соответствующему параметру в целевом объекте.
  • CS9200: значение по умолчанию указано для ref readonly параметра, но ref readonly должно использоваться только для ссылок. Рассмотрите возможность объявления параметра как in.
  • CS9201: поле ref следует назначить ref перед использованием.
  • CS9265: поле никогда не назначается ссылочным, и всегда будет иметь значение по умолчанию (ссылка null)

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

  • Удалите ссылочные параметры из индексаторов. Индексаторы предназначены для предоставления синтаксиса доступа, подобного массиву, и компилятор не может гарантировать безопасное отслеживание времени существования для ссылок, передаваемых через методы доступа индексатора (CS0631, CS1623).
  • Удалите ссылочные параметры из методов итератора. Итераторы выполняют код лениво в нескольких вызовах с помощью машин состояний, и компилятор не может гарантировать, что ссылочные переменные остаются допустимыми при переходе через границы yield return, где выполнение приостанавливается и возобновляется (CS1623).
  • Удалите ссылочные параметры из асинхронных методов. Асинхронные методы могут приостановить выполнение в точках ожидания и возобновить работу в разных потоках, что делает невозможным гарантировать, что ссылочные переменные остаются допустимыми и доступными во время выполнения метода (CS1988).
  • Избегайте использования выражений await внутри условных выражений ref. Операция await может приостановить выполнение и привести к аннулированию ссылок, выбираемых условным оператором, что может привести к потенциальному использованию аннулированных ссылок при возобновлении выполнения (CS8325).
  • Убедитесь, что обе ветви условного оператора возвращают ссылки или ни одна из них не возвращает ссылку. Когда обе возвращают ссылки, они должны быть одного и того же типа. Условный оператор должен создать согласованный тип результата, который можно безопасно использовать вызывающим кодом независимо от выбранной ветви (CS8326, CS8327).
  • Удалите значения по умолчанию из ref и out параметров. Параметры ссылок всегда должны быть предоставлены на месте вызова, чтобы установить необходимое отношение связывания между параметром и существующей переменной, что делает значения по умолчанию семантически бессмысленными (CS1741).
  • Избегайте объявления неявной типизированной out переменной в списке аргументов, который также ссылается на ту же переменную. Компилятор должен определить тип переменной из сигнатуры метода, одновременно проверяя использование этой переменной в том же выражении, создавая циклическую зависимость (CS8196).
  • Не передайте переменные диапазона запросов LINQ в качестве ссылочных параметров. Переменные диапазона — это переменные итерации, созданные компилятором, время существования которых управляется моделью выполнения запроса и не имеет стабильных расположений памяти, на которые можно безопасно ссылаться (CS1939).
  • При деконструкции объектов используйте простые переменные значений вместо ссылочных локальных переменных. Деконструкция создает новые переменные для получения деконструированных значений, и ссылочные переменные пытаются создать псевдонимы для этих временных переменных, а не хранить их самостоятельно (CS9072).
  • Избегайте реализации нескольких интерфейсов, где методы различаются только по модификаторам параметров ref по сравнению с out. Спецификация языка C# обрабатывает их как отдельные сигнатуры, но не предоставляет способ уточнения, какую реализацию следует вызывать, так как как ref и out используют один и тот же синтаксис вызова на границах реализации (CS0767).
  • Удалите ссылочные параметры из методов, помеченных System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute. Эти методы вызываются из неуправляемого кода, который не понимает правила безопасности ссылок на C#и не может гарантировать надлежащее управление временем существования ссылочных переменных через управляемую или неуправляемую границу (CS8977).
  • Используйте модификатор ref на первых параметрах метода расширения только для типов значений или универсальных типов, ограниченных типами значений. Ссылочные типы уже передаются по ссылке на уровне CLR, а добавление ref создало бы ссылку на ссылку, в то время как расширения типов значений с ref позволяют изменять расширенный экземпляр (CS8337, CS8338).
  • Не передавать события среды выполнения Windows в качестве ссылочных параметров. Эти события соответствуют системе типов среды выполнения Windows, срок жизни и правила работы с потоками которой отличаются от ссылок .NET и не поддерживают поведение псевдонимов, необходимое для ссылочных параметров C# (CS7084).
  • Удалите System.Runtime.InteropServices.OutAttribute из параметров ref readonly. Этот атрибут предназначен для маршалинга семантики в сценариях вызова платформы, где направление параметра – только выходящее, что противоречит гарантии ref readonly, что параметр ссылается на существующие данные, которые не будут переназначены (CS9199).
  • Убедитесь, что все поля ref в типе назначаются либо в инициализаторах полей, либо во всех путях кода конструктора до его завершения. Неинициализированные поля ссылок будут содержать недопустимые ссылки, которые могут привести к повреждению памяти при доступе (CS9201, CS9265).
  • Сопоставляйте модификаторы категории ссылок (ref, in, out, ref readonly) между методом и его переопределённым базовым методом или реализованным методом интерфейса. Модификатор ссылок является частью контракта сигнатуры метода, который производные типы должны учитывать для обеспечения заменяемости и ожиданий вызывающего (CS9196, CS9197, CS9198).
  • Объявите параметры in , а не ref readonly при предоставлении значений по умолчанию. ref readonly предназначен для сценариев, когда вызывающий объект передает ссылку на существующую переменную, в то время как in параметры могут принимать ссылки и временные копии значений, делая значения по умолчанию значимыми (CS9200).

Дополнительные сведения о том, где разрешены ссылочные переменные, см. в параметрах метода, итераторах, асинхронных шаблонах программирования и спецификации языка C#.

unscoped ref Ограничения

Квалификатор unscopedref параметров не допускается в некоторых расположениях:

  • CS9101: UnscopedRefAttribute может применяться только к методам и свойствам экземпляра структуры или виртуального интерфейса и не может применяться к конструкторам или элементам только для инициализации.
  • CS9102: не удается применить unscopedRefAttribute к реализации интерфейса, так как реализованный член не имеет этого атрибута.

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

  • Удалите модификатор unscoped или атрибут System.Diagnostics.CodeAnalysis.UnscopedRefAttribute из конструкторов структур и только для инициализации членов. Эти члены имеют специальную семантику инициализации, когда компилятор должен убедиться, что все ссылки не выходят за пределы этапа инициализации. Разрешение неуправляемых ссылок нарушает гарантию того, что инициализация завершится до того, как структура станет полностью доступной (CS9101).
  • unscoped Удалите модификатор из методов реализации интерфейса, если соответствующий метод интерфейса не имеет его. Неуправляемая характеристика влияет на контракт метода относительно гарантий времени существования ссылок, и реализации должны поддерживать тот же контракт, что и интерфейс, который они реализуют, чтобы гарантировать, что вызывающие пользователи могут полагаться на согласованное поведение времени существования независимо от того, какая реализация вызывается (CS9102).

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

Для ссылочных переменных требуется ссылка

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

  • CS0206: свойство или индексатор не ref-returning могут использоваться в качестве out значения или ref значения.
  • CS1510: переменная ref или out значение должна быть назначаемой переменной.

Предупреждения.

  • CS9191: ref модификатор аргумента, соответствующего параметруin, эквивалентенin. Вместо этого рекомендуется использоватьin.
  • CS9192: аргумент должен передаваться с ключевым словом ref или in ключевым словом.
  • CS9193: аргумент должен быть переменной, так как он передается параметру ref readonly .
  • CS9195: аргумент должен передаваться с ключевым словом in

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

  • Сохраните результат доступа к свойству или индексатору в локальной переменной перед передачей в качестве ссылочного параметра. Свойства и индексаторы — это методы , возвращающие значения, а не предоставляющие прямой доступ к расположениям хранилища, а эталонные параметры требуют фактической переменной с стабильным расположением памяти, которое можно псевдонимировать (CS0206, CS1510).
  • Используйте модификатор in вместо ref, когда передаете аргументы в параметры in. Хотя ref технически работает из-за обратной совместимости, in модификатор более четко выражает намерение, что аргумент доступен только для чтения и может быть передан более эффективно в качестве ссылки без копирования (CS9191, CS9195).
  • Добавьте соответствующий модификатор ссылок (ref, inили ref readonly) при передаче аргументов в параметры, ожидающие ссылки. Пропуская модификатор, компилятор может создать временную копию значения, которая неэффективна и может привести к неожиданному поведению, если вызывающий код ожидает, что изменения будут отражены в исходной переменной (CS9192, CS9193).

Дополнительные сведения о эталонных параметрах и передаче переменных по ссылке см. в параметрах метода, ключевом слове ref и спецификации языка C#.

Для записываемых ссылочных переменных требуется референт, доступный для записи

Для записываемой ссылочной переменной требуется, чтобы референт также был записываемым. Следующие ошибки указывают на то, что переменная не является записываемой:

  • CS0192: readonly поле нельзя использовать как значение ref или out значение (за исключением конструктора)
  • CS0199: static readonly поле нельзя использовать как ref значение или out значение (за исключением статического конструктора)
  • CS1605: не удается использовать переменную в качестве ref значения или out значения, так как она доступна только для чтения
  • CS1649: элементы readonly поля нельзя использовать как ref или out значение (за исключением конструктора)
  • CS1651: поля static readonly поля поля не могут использоваться как ref значение или out значение (за исключением статического конструктора)
  • CS1655: не удается использовать поля типа в качестве ref или out значения
  • CS1657: не удается использовать переменную в ref качестве значения или out значения
  • CS8329: не удается использовать переменную в качестве ref значения или out значения, так как это переменная для чтения
  • CS8330: элементы переменной нельзя использовать в качестве ref значения или out значения, так как это переменная для чтения
  • CS8331: не удается назначить переменную или использовать ее в качестве правой стороны ref назначения, так как это переменная считывания
  • CS8332: не удается назначить элемент переменной или использовать его в качестве правой стороны ref назначения, так как это переменная считывания

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

  • Скопируйте значение из поля чтения в локальную переменную и передайте локальную переменную в качестве ref или out параметра. Поля readonly неизменяемы после инициализации (кроме в конструкторах), и разрешение изменяемых ссылок на них нарушило бы гарантию неизменяемости, которую предоставляет readonly (CS0192, CS0199, CS1649, CS1651).
  • Используйте параметры ref readonly или in вместо ref или out, чтобы передавать только для чтения переменные, переменные итерации или другие незаписываемые значения по ссылке. Эти модификаторы указывают, что метод будет считывать только указанное значение, не пытаясь изменить его. Это соответствует ограничениям неизменяемости исходной переменной (CS1605, CS1655, CS1657, CS8329).
  • Скопируйте члены переменных только для чтения в локальные переменные перед передачей в качестве записываемых ссылок. Несмотря на то, что член сам по себе может не быть объявлен как readonly, доступ к нему осуществляется через readonly путь (через readonly поле, параметр или локальный), а компилятор применяет транзитивность , чтобы предотвратить непрямую мутацию readonly данных (CS8330, CS8332).
  • Избегайте записываемых назначений ссылок для чтения переменных, переменных итерации для кэширования, использования ресурсов инструкции или переменных фиксированной инструкции. Эти переменные имеют специальную семантику времени существования, управляемую компилятором. Переменная автоматически освобождается или удаляется в конце своей области действия. Внешние ссылки создают висящие ссылки после удаления (CS8331).

Дополнительные сведения о семантике readonly и ссылочных параметрах см. в ключевом слове readonly, модификаторе in параметров, ref readonly и Спецификации языка C#.