Erros e avisos associados a parâmetros de referência, variáveis e retornos
Os seguintes erros podem ser gerados quando você está trabalhando com variáveis de referência:
- CS0192: um campo
readonly
não pode ser usado como um valorref
ouout
(exceto em um construtor) - CS0199: um campo
static readonly
não pode ser usado como um valorref
ouout
(exceto em um construtor estático) - CS0206: propriedades ou indexadores que não retornem referências talvez não possam ser usados como um valor
out
ouref
- CS0631:
ref
eout
não são válidos neste contexto - CS0767: não é possível herdar a interface com os parâmetros de tipo especificados, porque isso faz com que o método contenha sobrecargas que diferem apenas em
ref
eout
- CS1510: um valor
ref
ouout
deve ser uma variável atribuível - CS1605: não é possível usar a variável como um valor
ref
ouout
porque ela é somente leitura - CS1623: os iteradores não podem ter parâmetros
ref
,in
ouout
- CS1649: os membros de um campo
readonly
não podem ser usados como um valorref
ouout
(exceto em um construtor) - CS1651: campos de um campo estático somente leitura não podem ser usados como um valor
ref
ouout
(exceto em um construtor estático) - CS1655: não é possível usar campos do tipo como um valor
ref
ouout
- CS1657: não é possível usar a variável como um valor
ref
ouout
- CS1741: um parâmetro
ref
ouout
não pode ter um valor padrão - CS1939: não é possível passar a variável de intervalo como um parâmetro
out
ouref
- CS1988: métodos assíncronos não podem ter parâmetros
ref
,in
ouout
- CS7084: um evento do Windows Runtime pode não ser passado como um parâmetro
out
ouref
. - CS8166: não é possível retornar um parâmetro por referência porque ele não é um parâmetro
ref
- CS8167: não é possível retornar por referência um membro do parâmetro porque ele não é um parâmetro
ref
ouout
- CS8168: não é possível retornar o local por referência porque não é um local de referência
- CS8169: não é possível retornar um membro da variável local por referência porque ele não é um local de referência
- CS8196: Referência a uma variável digitada implicitamente não é permitida na mesma lista de argumentos.
- CS8325: "
await
" não pode ser usado em uma expressão que contém um operador condicionalref
- CS8326: ambos os valores de operador condicional devem ser valores de referência ou nenhum deles pode ser um valor de referência
- CS8327: a expressão deve ser do tipo correto para corresponder ao valor de referência alternativo
- CS8329: não é possível usar a variável como um valor
ref
ouout
porque ela é uma variável somente leitura - CS8330: os membros da variável não podem ser usados como um valor
ref
ouout
porque é uma variável somente leitura - CS8331: não é possível atribuir à variável ou usá-la como o lado direito de uma atribuição
ref
porque ela é uma variável somente leitura - CS8332: não é possível atribuir a um membro da variável ou usá-la como o lado direito de uma atribuição
ref
porque ela é uma variável somente leitura - CS8337: o primeiro parâmetro de um método de extensão "
ref
" deve ser um tipo de valor ou um tipo genérico restrito ao struct. - CS8338: o primeiro parâmetro "
in
" ou "ref readonly
" do método de extensão deve ser um tipo de valor concreto (não genérico). - CS8351: branches de um operador condicional
ref
não podem se referir a variáveis com escopos de declaração incompatíveis - CS8373: o lado esquerdo de uma atribuição
ref
deve ser uma variável de referência. - CS8374: não é possível atribuir novamente, a origem tem um escopo de escape mais estreito do que o destino.
- CS8388: uma variável
out
não pode ser declarada como uma referência local - CS8977: não é possível usar "
ref
", "in
" ou "out
" na assinatura de um método atribuído com "UnmanagedCallersOnly". - CS9072: uma variável de desconstrução não pode ser declarada como uma referência local
- CS9077: não é possível retornar um parâmetro por referência por meio de um parâmetro
ref
; ele só pode ser retornado em uma instrução return - CS9078: não é possível retornar por referência um membro do parâmetro por meio de um parâmetro
ref
; ele só pode ser retornado em uma instrução return - CS9079: não é possível atribuir novamente porque a origem só pode escapar do método atual por meio de uma instrução de retorno.
- CS9096: não é possível atribuir novamente porque a origem tem um escopo de escape de valor mais amplo do que o destino, permitindo a atribuição por meio de fonte de valores com escopos de escape mais estreitos do que o destino.
- CS9101: UnscopedRefAttribute só pode ser aplicado a métodos e propriedades de instância de struct ou interface virtual e não pode ser aplicado a construtores ou membros somente init.
- CS9102: UnscopedRefAttribute não pode ser aplicado a uma implementação de interface porque o membro implementado não tem esse atributo.
- CS9104: um recurso de instrução
using
do tipo não pode ser usado em métodos assíncronos ou expressões lambda assíncronas. - CS9190: o modificador
readonly
deve ser especificado apósref
. - CS9199: um parâmetro
ref readonly
não pode ter o atributo Out.
Os seguintes avisos são gerados quando variáveis de referência são usadas incorretamente:
- CS9085: essa referência atribui variável, mas o destino tem um escopo de escape mais estreito que a origem.
- CS9086: os branches do operador condicional
ref
referem-se a variáveis com escopos de declaração incompatíveis - CS9087: isso retorna um parâmetro por referência, mas não é um parâmetro
ref
- CS9089: isso retorna por referência um membro do parâmetro que não é um parâmetro
ref
ouout
- CS9091: isso retorna o local por referência, mas não é uma referência local
- CS9092: isso retorna um membro do local por referência, mas não é uma referência local
- CS9093: essa referência atribui, mas a origem só pode escapar do método atual por meio de uma instrução de retorno.
- CS9094: isso retorna um parâmetro por referência por meio de um parâmetro
ref
; mas ele só pode ser retornado com segurança em uma instrução return - CS9095: isso retorna por referência um membro do parâmetro por meio de um parâmetro
ref
; mas ele só pode ser retornado com segurança em uma instrução return - CS9097: essa referência atribui, mas a origem tem um escopo de escape de valor mais amplo do que o destino, o que permite a atribuição por meio de destino de valores com escopos de escape mais estreitos do que a origem.
- CS9191: o modificador
ref
do argumento correspondente ao parâmetroin
é equivalente ain
. Considere usarin
em vez disso. - CS9192: o argumento deve ser passado com a palavra-chave
ref
ouin
. - CS9193: o argumento deve ser uma variável porque é passado para um parâmetro
ref readonly
- CS9195: o argumento deve ser passado com a palavra-chave
in
- CS9196: o modificador de tipo de referência do parâmetro não corresponde ao parâmetro correspondente no membro substituído ou implementado.
- CS9197: o modificador de tipo de referência do parâmetro não corresponde ao parâmetro correspondente no membro oculto.
- CS9198: o modificador de tipo de referência do parâmetro não corresponde ao parâmetro correspondente no destino.
- CS9200: um valor padrão é especificado para o parâmetro
ref readonly
, masref readonly
deve ser usado apenas para referências. Considere declarar o parâmetro comoin
. - CS9201: o campo Ref deve ser atribuído novamente antes do uso.
- CS9265: O campo nunca é atribuído a referência e sempre terá seu valor padrão (referência nula)
Estes erros e avisos seguem estes temas:
- Sintaxe incorreta: a sintaxe de sua declaração ou uso é inválida.
- A linguagem constrói onde as variáveis
ref
não são válidas: alguns idiomas C# não permitem variáveis. Normalmente, isso ocorre porque a análise de segurança de referência não pode ser executada de forma confiável. - Expressão de valor usada onde uma variável de referência é necessária: a expressão usada como uma variável de referência deve ser uma variável, não uma expressão de valor.
- Variáveis de referência graváveis que se referem a variáveis readonly: uma referência a uma variável readonly não pode ser passada por referência gravável.
- violações de segurança de referência: uma variável de referência não pode se referir a uma variável que tenha um contexto mais estreito. Isso significa que a variável de referência pode se referir à memória inválida.
Este artigo usa a variável de referência do termo como um termo geral para um parâmetro declarado com um dos modificadores in
, ref readonly
, ref
ou out
ou uma variável local ref
, um campo ref
em um ref struct
ou um retorno ref
. Uma variável de referência refere-se a outra variável, chamada de referencial.
Sintaxe incorreta
Esses erros indicam que você está usando a sintaxe incorreta em relação às variáveis de referência:
- CS8373: o lado esquerdo de uma atribuição
ref
deve ser uma variável de referência. - CS8388: uma variável
out
não pode ser declarada como um local de referência. - CS9190: o modificador
readonly
deve ser especificado apósref
.
Você pode corrigir o erro com uma destas alterações:
- O operando esquerdo de um operador
= ref
deve ser uma variável de referência. Para obter mais informações sobre a sintaxe correta, confira variáveis de referência. - O modificador de parâmetro
ref readonly
deve estar nessa ordem.readonly ref
não é um modificador de parâmetro legal. Alterne a ordem das palavras. - Uma variável local não pode ser declarada como
out
. Para declarar uma variável de referência local, useref
.
Restrições de variável de referência
Os erros a seguir indicam que uma variável de referência não pode ser usada onde você tem:
- CS0631:
ref
eout
não são válidos neste contexto - CS0767: não é possível herdar a interface com os parâmetros de tipo especificados porque isso faz com que o método contenha sobrecargas que diferem apenas em
ref
eout
- CS1623: iteradores não podem ter parâmetros
ref
,in
ouout
- CS1741: Um parâmetro
ref
ouout
não pode ter um valor padrão - CS1939: não é possível passar a variável de intervalo como um parâmetro
out
ouref
- CS1988: métodos assíncronos não podem ter parâmetros
ref
,in
ouout
- CS7084: um evento do Windows Runtime pode não ser passado como um parâmetro
out
ouref
. - CS8196: Referência a uma variável
out
digitada implicitamente não é permitida na mesma lista de argumentos. - CS8325: "await" não pode ser usado em uma expressão que contém um operador condicional
ref
- CS8326: ambos os valores de operador condicional devem ser valores de referência ou nenhum deles pode ser um valor de referência
- CS8327: a expressão deve ser do tipo correto para corresponder ao valor de referência alternativo
- CS8337: o primeiro parâmetro de um método de extensão "
ref
" deve ser um tipo de valor ou um tipo genérico restrito ao struct. - CS8338: o primeiro parâmetro "
in
" ou "ref readonly
" do método de extensão deve ser um tipo de valor concreto (não genérico). - CS8977: não é possível usar "
ref
", "in
" ou "out
" na assinatura de um método atribuído com "UnmanagedCallersOnly". - CS9072: uma variável de desconstrução não pode ser declarada como uma referência local
- CS9104: um recurso de instrução
using
do tipo não pode ser usado em métodos assíncronos ou expressões lambda assíncronas. - CS9199: um parâmetro
ref readonly
não pode ter o atributo Out.
Os avisos a seguir indicam que uma variável de referência não deve ser usada e pode não ser segura:
- CS9196: o modificador de tipo de referência do parâmetro não corresponde ao parâmetro correspondente no membro substituído ou implementado.
- CS9197: o modificador de tipo de referência do parâmetro não corresponde ao parâmetro correspondente no membro oculto.
- CS9198: o modificador de tipo de referência do parâmetro não corresponde ao parâmetro correspondente no destino.
- CS9200: um valor padrão é especificado para o parâmetro
ref readonly
, masref readonly
deve ser usado apenas para referências. Considere declarar o parâmetro comoin
. - CS9201: o campo Ref deve ser atribuído novamente antes do uso.
- CS9265: O campo nunca é atribuído a referência e sempre terá seu valor padrão (referência nula)
Para corrigir o erro, remova a variável de referência onde ela não é permitida:
- Remova os parâmetros
in
,ref
eout
dos indexadores, iteradores e métodos assíncronos. - Remova expressões condicionais de referência (
? :
) que incluem um await. - Remova o modificador
ref
do primeiro parâmetro de um método de extensão em que esse tipo não é um tipo de valor ou um tipo genérico restrito como um tipo de valor. - Ambas as [expressões de operador condicional] ou nenhuma delas devem ser variáveis
ref
. Removaref
de uma expressão ou adicione-o à outra. Se for uma expressão condicionalref
, ambas as expressões deverão ser do mesmo tipo. - Os parâmetros
ref
eout
não podem ter valores padrão. Remova o modificadorref
ouout
ou remova o valor padrão. - Uma declaração de variável
out
digitada implicitamente também não pode aparecer em outro lugar na mesma lista de argumentos. - Você não pode colocar variáveis de referência em uma instrução
using
em métodos de expressões lambdaasync
. - A variável de intervalo em uma expressão de consulta LINQ não pode ser passada por referência.
- Não é possível desconstruir um objeto em variáveis de referência. Substitua as variáveis de referência por variáveis de valor.
- Você não pode implementar várias interfaces em que as sobrecargas de método diferem apenas em
ref
eout
. Por exemplo, uma interface declaravoid M(ref int i)
e outra interface declaravoid M(out int i)
. Uma classe não pode implementar ambas as interfaces porque os métodos não são distinguíveis. Você só pode implementar uma dessas interfaces. - Métodos atribuídos com System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute não podem usar parâmetros de referência.
- Um evento de runtime do Windows não pode ser passado como uma variável de referência.
- Um parâmetro
ref readonly
não pode ter o System.Runtime.InteropServices.OutAttribute aplicado a ele na API de comunicação remota. - Inicialize um
ref
campo no construtor ou como um inicializador de campo.
Restrições unscoped ref
O qualificador unscoped
em parâmetros ref
não é permitido em alguns locais:
- CS9101: UnscopedRefAttribute só pode ser aplicado a métodos e propriedades de interface virtual ou instância de struct e não pode ser aplicado a construtores ou membros somente init.
- CS9102: UnscopedRefAttribute não pode ser aplicado a uma implementação de interface porque o membro implementado não tem esse atributo.
Você deve remover o modificador unscoped
na declaração de parâmetro que causou o erro.
As variáveis de referência exigem um referencial
Você deve fornecer uma variável como um argumento para um parâmetro de referência, retorno de referência ou atribuição local ref:
- CS0206: Uma propriedade ou indexador que não retorna uma referência pode não ser usada como um valor
out
ouref
- CS1510: O valor
ref
ouout
deve ser uma variável atribuível
Avisos:
- CS9191: O modificador
ref
do argumento correspondente ao parâmetroin
é equivalente ain
. Considere usarin
em vez disso. - CS9192: o argumento deve ser passado com a palavra-chave
ref
ouin
. - CS9193: o argumento deve ser uma variável porque é passado para um parâmetro
ref readonly
- CS9195: o argumento deve ser passado com a palavra-chave
in
O compilador emite esses erros quando você usa uma expressão que calcula um valor em que uma variável deve ser usada. Você deve armazenar o resultado dessa expressão em uma variável para usá-la. Por exemplo, propriedades e indexadores retornam valores, não variáveis. Você deve armazenar o resultado em uma variável e passar uma referência para essa variável.
Variáveis de referência graváveis exigem um referencial gravável
Uma variável de referência gravável requer que o referencial também seja gravável. Os seguintes erros indicam que a variável não é gravável:
- CS0192: um campo
readonly
não pode ser usado como um valorref
ouout
(exceto em um construtor) - CS0199: um campo
static readonly
não pode ser usado como um valorref
ouout
(exceto em um construtor estático) - CS1605: não é possível usar a variável como um valor
ref
ouout
porque ela é somente leitura - CS1649: os membros de um campo
readonly
não podem ser usados como um valorref
ouout
(exceto em um construtor) - CS1651: campos de um campo
static readonly
não podem ser usados como um valorref
ouout
(exceto em um construtor estático) - CS1655: não é possível usar campos do tipo como um valor
ref
ouout
- CS1657: não é possível usar variável como um valor
ref
ouout
- CS8329: não é possível usar a variável como um valor
ref
ouout
porque ela é uma variável somente leitura - CS8330: os membros da variável não podem ser usados como um valor
ref
ouout
porque é uma variável somente leitura - CS8331: não é possível atribuir à variável ou usá-la como o lado direito de uma atribuição
ref
porque ela é uma variável somente leitura - CS8332: não é possível atribuir a um membro da variável ou usá-la como o lado direito de uma atribuição
ref
porque ela é uma variável somente leitura
Exemplos de variáveis que não são graváveis incluem:
- Campos readonly, tanto campos de instância quanto campos estáticos.
- Membros de campos
readonly
. - A variável
this
. - A variável de iteração foreach
- Uma variável de uso ou uma variável fixa.
Você deve copiar o valor e passar uma referência para a cópia.
Violações de segurança de referência
O compilador controla o contexto seguro de referenciais e variáveis de referência. O compilador emite erros ou avisos em código não seguro, quando uma variável de referência se refere a uma variável referencial que não é mais válida. O referencial deve ter um contexto seguro que seja pelo menos tão largo quanto o contexto de segurança de referência da variável de referência. Violar essas verificações de segurança significa que a variável de referência acessa a memória aleatória em vez da variável referencial.
- CS8166: não é possível retornar um parâmetro por referência porque ele não é um parâmetro
ref
- CS8167: não é possível retornar por referência um membro do parâmetro porque ele não é um parâmetro
ref
ouout
- CS8168: não é possível retornar o local por referência porque não é um local de referência
- CS8169: não é possível retornar um membro da variável local por referência porque ele não é um local de referência
- CS8345: a propriedade de campo ou implementada automaticamente não pode ser do tipo, a menos que seja um membro de instância de um
ref struct
. - CS8351: branches de um operador condicional
ref
não podem se referir a variáveis com escopos de declaração incompatíveis - CS8374: não é possível referência, a origem tem um escopo de escape mais estreito do que o destino.
- CS9077: não é possível retornar um parâmetro por referência por meio de um parâmetro
ref
; ele só pode ser retornado em uma instrução return - CS9078: não é possível retornar por referência um membro do parâmetro por meio de um parâmetro
ref
; ele só pode ser retornado em uma instrução return - CS9079: não é possível atribuir novamente a origem ao destino porque a origem só pode escapar do método atual por meio de uma instrução de retorno.
- CS9096: não é possível atribuir novamente a origem ao destino porque a origem tem um escopo de escape de valor mais amplo do que o destino, o que permite a atribuição por meio de destino de valores com escopos de escape mais estreitos do que a origem.
Avisos:
- CS9085: essa referência atribui a origem ao destino, mas a origem tem um escopo de escape mais estreito do que o destino.
- CS9086: os branches do operador condicional de referência referem-se a variáveis com escopos de declaração incompatíveis
- CS9087: isso retorna um parâmetro por referência, mas não é um parâmetro
ref
- CS9089: isso retorna por referência um membro do parâmetro que não é um parâmetro
ref
ouout
- CS9091: isso retorna o local por referência, mas não é uma referência local
- CS9092: isso retorna um membro do local por referência, mas não é uma referência local
- CS9093: essa referência atribui a origem ao destino, mas a origem só pode escapar do método atual por meio de uma instrução de retorno.
- CS9094: isso retorna um parâmetro por referência por meio de um parâmetro
ref
; mas ele só pode ser retornado com segurança em uma instrução return - CS9095: isso retorna por referência um membro do parâmetro por meio de um parâmetro
ref
; mas ele só pode ser retornado com segurança em uma instrução return - CS9097: essa referência atribui a origem ao destino, mas a origem tem um escopo de escape de valor mais amplo do que o destino, permitindo a atribuição por meio de destino de valores com escopos de escape mais estreitos do que a origem.
O compilador usa a análise estática para determinar se o referencial é válido em todos os pontos em que a variável de referência pode ser usada. Você precisa refatorar o código para que o referencial permaneça válido em todos os locais em que a variável de referência possa se referir a ele. Para obter detalhes sobre as regras de segurança de referência, confira o padrão C# em contextos de segurança de referência.