Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
При работе с ссылочными переменными могут возникать следующие ошибки:
-
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)
Эти ошибки и предупреждения соответствуют следующим темам:
- Неправильный синтаксис: синтаксис объявления или использования недопустим.
-
Языковые конструкции, в которых
refпеременные недопустимы: некоторые идиомы C# не допускают переменные. Обычно это связано с тем, что анализ безопасности ссылок не может быть выполнен надежно. - Выражение значения, используемое при необходимости ссылочной переменной: выражение, используемое в качестве ссылочной переменной, должно быть переменной, а не выражением значения.
- Записываемые ссылочные переменные, ссылающиеся на переменные для чтения: ссылка на переменную, доступная для чтения, не может передаваться путем записи ссылки.
В этой статье используется переменная ссылки на термин в качестве общего термина для параметра, объявленного с одним из 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#.