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

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

  • CS0192: readonly поле нельзя использовать в качестве значения ref или out (за исключением конструктора)
  • CS0199: static readonly поле нельзя использовать в качестве значения ref или out (за исключением статического конструктора)
  • CS0206: Свойство или индексатор, не возвращающие ref, не могут использоваться в качестве значения out или ref
  • CS0631: ref и out недопустимы в этом контексте
  • CS0767: Не удается унаследовать интерфейс с указанными параметрами типа, поскольку это приведет к тому, что метод будет содержать перегрузки, отличающиеся только по ref и out
  • CS1510: Значение ref или out должно быть переменной, которой можно присвоить значение
  • CS1605: Невозможно использовать переменную в качестве значения ref или out, поскольку она доступна только для чтения
  • CS1623: Итераторы не могут иметь параметры ref, in или out
  • CS1649: элементы readonly поля нельзя использовать как ref или out значение (за исключением конструктора)
  • CS1651: Поля статического поля только для чтения нельзя использовать в качестве значения ref или out (за исключением статического конструктора)
  • CS1655: Невозможно использовать поля типа как значение ref или out
  • CS1657: Невозможно использовать переменную в качестве значения ref или out
  • CS1741: Параметр ref или out не может иметь значение по умолчанию
  • CS1939: не удается передать переменную диапазона в качестве out или ref параметра
  • CS1988: асинхронные методы не могут иметь параметры ref, in или 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 присваивания должна быть переменной ref.
  • CS8388: out переменная не может быть объявлена как локальная ссылка
  • CS8977: Не удается использовать 'ref', 'in' или 'out' в сигнатуре метода, помеченного атрибутом 'UnmanagedCallersOnly'.
  • CS8986: модификатор "scoped" параметра не соответствует целевому объекту.
  • CS8987: модификатор "scoped" параметра не совпадает с переопределенным или реализованным элементом.
  • CS9061: модификатор scoped нельзя использовать с выбросом.
  • CS9062: Типы и псевдонимы не могут называться 'scoped'.
  • CS9063: UnscopedRefAttribute не может быть применен к этому параметру, потому что он по умолчанию не имеет области действия.
  • CS9065: не используйте System.Runtime.CompilerServices.ScopedRefAttribute. Вместо этого используйте ключевое слово scoped.
  • CS9066: unscopedRefAttribute нельзя применить к параметрам, имеющим модификатор "scoped".
  • CS9072: Переменная деконструкции не может быть объявлена как локальная переменная ref
  • 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: Полю никогда не присваивается значение по ссылке, и оно всегда будет иметь значение по умолчанию (пустая ссылка)

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

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

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

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

  • CS8373: В левой части ref присваивания должна быть переменная 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: Итераторы не могут иметь параметры ref, in или out
  • CS1741: Параметр ref или out не может иметь значение по умолчанию
  • CS1939: не удается передать переменную диапазона в качестве out или ref параметра
  • CS1988: Асинхронные методы не могут иметь параметры ref, in или out
  • CS7084: Событие среды выполнения Windows не может передаваться в качестве параметра out или ref.
  • CS8196: ссылка на неявную переменную типа out не допускается в том же списке аргументов.
  • CS8325: "await" не может использоваться в выражении, содержаемом условным оператором ref
  • CS8326: Оба значения условного оператора должны быть значениями ref, либо ни одно из них не должно быть значением ref
  • CS8327: выражение должно иметь правильный тип, чтобы соответствовать альтернативному значению ссылок
  • CS8337: первый параметр метода расширения "ref" должен быть типом значения или универсальным типом, ограниченным структурой.
  • CS8338: первый параметр "" илиin "ref readonly" метода расширения должен быть конкретным (не универсальным) типом значения.
  • CS8977: Невозможно использовать 'ref', 'in' или 'out' в сигнатуре метода, помеченного атрибутом "UnmanagedCallersOnly".
  • CS9072: переменная деконструкции не может быть объявлена как локальная переменная ref
  • CS9104: Ресурс инструкции типа using нельзя использовать в асинхронных методах или асинхронных лямбда-выражениях.
  • CS9199: ref readonly параметр не может иметь атрибут Out.

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

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

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

  • Удалите ссылочные параметры из индексаторов. Индексаторы предназначены для предоставления синтаксиса доступа, подобного массиву, и компилятор не может гарантировать безопасное отслеживание времени существования для ссылок, передаваемых через методы доступа индексатора (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 Ограничения

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

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

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

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

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

Ссылочные переменные должны иметь объект, на который они ссылаются

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

  • CS0206: Свойство или индексатор, не возвращающие значение по ссылке, нельзя использовать в качестве значения 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#.