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 readonly campo não pode ser usado como um ref ou out valor (exceto em um construtor)
  • CS0199: Um static readonly campo não pode ser usado como um ref ou out valor (exceto em um construtor estático)
  • CS0206: Uma propriedade ou um indexador que não devolva uma referência ref não podem ser usados como um valor out ou ref
  • CS0631: ref e out não são válidos neste contexto
  • CS0767: Não é possível herdar a interface com os parâmetros de tipo especificados porque faz com que o método contenha sobrecargas que diferem apenas em ref e out
  • CS1510: Um ref ou out valor deve ser uma variável atribuível
  • CS1605: Não é possível usar a variável como valor de um ref ou out porque é apenas de leitura
  • CS1623: Os iteradores não podem ter ref, in ou out parâmetros
  • CS1649: Membros de um readonly campo não podem ser usados como um ref ou out valor (exceto em um construtor)
  • CS1651: Os campos de um campo estático só de leitura não podem ser usados como valor de ref ou out (exceto num construtor estático)
  • CS1655: Não é possível usar campos do tipo como um ref ou out valor
  • CS1657: Não é possível usar variável como um ref ou out valor
  • CS1741: Um ref ou out parâmetro não pode ter um valor padrão
  • CS1939: Não é possível passar a variável de intervalo como um out ou ref parâmetro
  • CS1988: Os métodos assíncronos não podem ter parâmetros ref, in ou out
  • CS7084: Um evento do Windows Runtime não pode ser passado como parâmetro out ou ref.
  • CS8196: A 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 contenha um ref operador condicional
  • CS8326: Ambos os valores de operador condicional devem ser valores ref ou nenhum pode ser um valor ref
  • CS8327: A expressão deve ser do tipo correto para corresponder ao valor ref alternativo
  • CS8329: Não é possível usar a variável como um ref ou out valor porque é uma variável somente leitura
  • CS8330: Os membros de uma variável não podem ser utilizados como valor ref ou out porque é uma variável só de leitura
  • CS8331: Não é possível atribuir à variável nem usá-la como o lado direito de uma atribuição ref porque é uma variável só de leitura
  • CS8332: Não é possível atribuir a um membro de uma variável nem utilizá-lo como o lado direito de uma ref atribuição, porque é uma variável só de 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 a 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).
  • CS8373: O lado esquerdo de uma ref atribuição deve ser uma variável ref.
  • CS8388: Uma out variável não pode ser declarada como uma ref local
  • CS8977: Não é possível usar 'ref', 'in', ou 'out' na assinatura de um método atribuído com 'UnmanagedCallersOnly'.
  • CS8986: O modificador 'visado' do parâmetro não corresponde ao alvo.
  • CS8987: O modificador 'scoped' do parâmetro não corresponde ao membro sobrescrito ou implementado.
  • CS9061: O modificador 'com escopo' não pode ser usado com descartar.
  • CS9062: Tipos e pseudónimos não podem ser chamados de 'scoped'.
  • CS9063: UnscopedRefAttribute não pode ser aplicado a este parâmetro porque, por defeito, não tem escopo.
  • CS9065: Não use 'System.Runtime.CompilerServices.ScopedRefAttribute'. Use a palavra-chave 'scoped' em vez disso.
  • CS9066: UnscopedRefAttribute não pode ser aplicado a parâmetros que tenham um modificador 'scoped'.
  • CS9072: Uma variável de desconstrução não pode ser declarada como uma ref local
  • CS9101: UnscopedRefAttribute só pode ser aplicado a métodos e propriedades de instância de structs ou de interfaces virtuais, e não pode ser aplicado a construtores ou membros exclusivos de inicialização.
  • CS9102: UnscopedRefAttribute não pode ser aplicado a uma implementação de interface porque o membro implementado não tem esse atributo.
  • CS9104: Um using recurso de instrução do tipo não pode ser usado em métodos assíncronos ou expressões lambda assíncronas.
  • CS9190: readonly modificador deve ser especificado após ref.
  • CS9199: Um ref readonly parâmetro não pode ter o atributo out.

Os seguintes avisos são gerados quando as variáveis de referência são usadas incorretamente:

  • CS9073: O modificador 'visado' do parâmetro não corresponde ao alvo.
  • CS9074: O modificador 'scoped' do parâmetro não corresponde ao membro substituído ou implementado.
  • CS9191: O ref modificador para o argumento correspondente ao in parâmetro é equivalente a in. Considere usar in em vez disso.
  • CS9192: Argumento deve ser passado com ref ou in palavra-chave.
  • CS9193: Argumento deve ser uma variável porque é passado para um ref readonly parâmetro
  • CS9195: Argumento deve ser passado com a in palavra-chave
  • 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 ref readonly parâmetro, mas ref readonly deve ser usado apenas para referências. Considere declarar o parâmetro como in.
  • CS9201: O campo Ref deve ser atribuído a ref antes do uso.
  • CS9265: O campo nunca recebe uma atribuição por referência e terá sempre o seu valor predefinido (referência nula)

Estes erros e avisos seguem estes temas:

Este artigo usa o termo variável de referência como termo genérico para um parâmetro declarado com um dos modificadores in, ref readonly, ref ou out, ou uma variável local ref, um campo ref num ref struct ou um retorno ref. Uma variável de referência refere-se a outra variável, chamada referente.

Sintaxe incorreta

Esses erros indicam que você está usando 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 ref.
  • CS8388: Uma out variável não pode ser declarada como uma ref local.
  • CS9190: readonly modificador deve ser especificado após ref.

Para corrigir estes erros:

  • Certifique-se de que o operando esquerdo de um = ref operador seja uma variável de referência em lugar de uma expressão de valor ou um local não de referência. A atribuição de referências exige que ambos os lados sejam variáveis de referência capazes de criar um alias para o mesmo local de armazenamento (CS8373).
  • Ao declarar parâmetros de referência, escreva o modificador como ref readonly em vez de readonly ref. A especificação da linguagem C# exige que a ref palavra-chave preceda o readonly modificador nas declarações de parâmetros para manter uma sintaxe consistente em todos os tipos de parâmetros de referência (CS9190).
  • Use a ref palavra-chave em vez de out quando declarar variáveis de referência locais. outé exclusivamente um modificador de parâmetro que indica que um método deve atribuir um valor antes de devolver, enquanto ref é a palavra-chave apropriada para criar variáveis locais que apelidificam outras localizações de armazenamento (CS8388). Para mais informações sobre variáveis de referência e os seus requisitos de sintaxe, consulte variáveis de referência e a Especificação da Linguagem C#.

Restrições de variáveis de referência

Os seguintes erros indicam que uma variável de referência não pode ser usada onde você tem uma:

  • CS0631: ref e out não são válidos neste contexto
  • CS0767: Não é possível herdar a interface com os parâmetros de tipo especificados porque faz com que o método contenha sobrecargas que diferem apenas em ref e out
  • CS1623: Os iteradores não podem ter ref, in ou out parâmetros
  • CS1741: Um ref ou out parâmetro não pode ter um valor padrão
  • CS1939: Não é possível passar a variável de intervalo como um out ou ref parâmetro
  • CS1988: Os métodos assíncronos não podem ter parâmetros ref, in ou out
  • CS7084: Um evento do Windows Runtime não pode ser passado como um parâmetro out ou ref.
  • CS8196: A referência a uma variável digitada out implicitamente não é permitida na mesma lista de argumentos.
  • CS8325: 'await' não pode ser usado em uma expressão que contenha um ref operador condicional
  • CS8326: Ambos os valores de operador condicional devem ser valores ref ou nenhum pode ser um valor ref
  • CS8327: A expressão deve ser do tipo correto para corresponder ao valor ref 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 a 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 ref local
  • CS9104: Um using recurso de instrução do tipo não pode ser usado em métodos assíncronos ou expressões lambda assíncronas.
  • CS9199: Um ref readonly parâmetro 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 ref readonly parâmetro, mas ref readonly deve ser usado apenas para referências. Considere declarar o parâmetro como in.
  • CS9201: O campo ref deve ter uma atribuição ref antes de ser utilizado.
  • CS9265: Ao campo nunca é atribuída uma referência e terá sempre o valor predefinido (referência nula)

Para corrigir estes erros:

  • Remover parâmetros de referência dos indexadores. Os indexadores são concebidos para fornecer uma sintaxe de acesso semelhante a um array e o compilador não pode garantir um rastreio seguro ao longo da vida para referências passadas através de acessores indexadores (CS0631, CS1623).
  • Remover parâmetros de referência dos métodos iteradores. Os iteradores executam código preguiçosamente através de múltiplas chamadas usando máquinas de estados, e o compilador não pode garantir que as variáveis referenciadas permanecem válidas através dos limites de yield return onde a execução é suspensa e retomada (CS1623).
  • Remover parâmetros de referência dos métodos assíncronos. Métodos assíncronos podem suspender a execução em pontos de espera e retomar em diferentes threads, tornando impossível garantir que as variáveis referenciadas permaneçam válidas e acessíveis durante toda a execução do método (CS1988).
  • Evite usar expressões await dentro das expressões condicionais ref. A operação await pode suspender a execução e invalidar as referências selecionadas pelo operador condicional, levando à possível utilização de referências invalidadas quando a execução for retomada (CS8325).
  • Assegure que ambos os ramos de um operador condicional ref retornem referências ou nenhum retorne uma referência, e quando ambos são referências, estas devem ser do mesmo tipo. O operador condicional deve produzir um tipo de resultado consistente que possa ser usado em segurança pelo código de chamada, independentemente do ramo selecionado (CS8326, CS8327).
  • Remova os valores predefinidos dos ref parâmetros e out . Os parâmetros de referência devem ser sempre fornecidos no local da chamada para estabelecer a relação de aliasing necessária entre o parâmetro e uma variável existente, tornando os valores padrão semanticamente sem significado (CS1741).
  • Evite declarar uma variável tipada out implicitamente numa lista de argumentos que também faça referência a essa mesma variável. O compilador deve inferir o tipo da variável a partir da assinatura do método enquanto valida simultaneamente os usos dessa variável dentro da mesma expressão, criando uma dependência circular (CS8196).
  • Não passe variáveis de intervalo de consulta LINQ como parâmetros de referência. As variáveis de intervalo são variáveis de iteração geradas pelo compilador cujo tempo de vida é gerido pelo modelo de execução da consulta e não possuem localizações de memória estáveis que possam ser referenciadas em segurança (CS1939).
  • Use variáveis de valor normais em vez de referências locais ao desconstruir objetos. A desconstrução cria novas variáveis para receber os valores desconstruídos e as variáveis de referência tentariam usar um alias destes valores temporários em vez de os armazenar independentemente (CS9072).
  • Evite implementar múltiplas interfaces onde os métodos diferem apenas pelos modificadores ref e out nos parâmetros. A especificação da linguagem C# trata estas como assinaturas distintas, mas não fornece uma forma de desambiguar qual implementação chamar, uma vez que ambos ref partilham out a mesma sintaxe de chamada nos limites da implementação (CS0767).
  • Remover parâmetros de referência dos métodos decorados com System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute. Estes métodos podem ser chamados a partir de código não gerido que não compreende as regras de segurança de referência do C# e não garante uma gestão adequada ao longo da vida útil das variáveis referenciadas através do limite gerido/não gerido (CS8977).
  • Use o ref modificador no primeiro parâmetro do método de extensão apenas para tipos de valor ou tipos genéricos restritos a tipos de valor. Os tipos de referência já são passados por referência ao nível do CLR e a adição ref criaria uma referência para uma referência, enquanto extensões de tipo de valor com ref possibilitam a mutação da instância estendida (CS8337, CS8338).
  • Não passe eventos de Runtime do Windows como parâmetros de referência. Estes eventos seguem o sistema de tipos Windows Runtime, que tem uma duração de vida e semântica de threading diferente das referências .NET e não suporta o comportamento de aliasing exigido pelos parâmetros de referência C# (CS7084).
  • Remova o System.Runtime.InteropServices.OutAttribute dos parâmetros ref readonly. Este atributo foi concebido para organizar semântica em cenários de invocação de plataforma onde a direção do parâmetro é apenas de saída, o que entra em conflito com ref readonlya garantia de que o parâmetro faz referência a dados existentes que não serão reatribuídos (CS9199).
  • Assegure que todos ref os campos de um tipo são atribuídos quer nos inicializadores de campo, quer em todos os caminhos do código do construtor, antes de o construtor ser concluído. Campos ref não inicializados conteriam referências inválidas que poderiam levar à corrupção da memória se acedidas (CS9201, CS9265).
  • Compare os modificadores de tipo de referência (ref, in, out, ref readonly) entre um método e o seu método base sobreposto ou método de interface implementado. O modificador de referência faz parte do contrato de assinatura do método que os tipos derivados devem respeitar para manter a substituibilidade e as expectativas do chamador (CS9196, CS9197, CS9198).
  • Declare parâmetros como in em vez de ref readonly quando fornecer valores por defeito. ref readonly é concebido para cenários em que o chamador passa uma referência a uma variável existente, enquanto in os parâmetros podem aceitar tanto referências como cópias temporárias de valores, tornando os valores padrão significativos (CS9200).

Para mais informações sobre onde as variáveis de referência são permitidas, veja Parâmetros de método, Iteradores, Padrões de programação assíncrona e a Especificação da Linguagem C#.

unscoped ref Restrições

O qualificador unscoped nos parâmetros ref não é permitido em alguns contextos:

  • 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 apenas de init.
  • CS9102: UnscopedRefAttribute não pode ser aplicado a uma implementação de interface porque o membro implementado não tem este atributo.

Para corrigir estes erros:

  • Remova o unscoped modificador ou o System.Diagnostics.CodeAnalysis.UnscopedRefAttribute atributo dos construtores struct e dos membros apenas de init. Estes membros têm uma semântica especial de inicialização onde o compilador deve garantir que quaisquer referências não persistam além da fase de inicialização, e a permissão de referências sem âmbito violaria a garantia de que a inicialização se conclui antes de a estrutura se tornar totalmente acessível (CS9101).
  • Remova o unscoped modificador dos métodos de implementação de interface quando o método correspondente não o tem. A característica sem escopo afeta o contrato do método no que diz respeito às garantias de duração das referências, e as implementações devem manter o mesmo contrato da interface que estão a implementar para garantir que os chamadores possam confiar num comportamento de duração consistente, independentemente da implementação invocada (CS9102).

Para mais informações sobre referências com e sem escopo, veja Parâmetros de Método e Restrição de contexto seguro na especificação da linguagem C#.

As variáveis de referência requerem um referente

Você deve fornecer uma variável como argumento para um parâmetro de referência, retorno de referência ou atribuição local de referência:

  • CS0206: Uma propriedade ou indexador que não devolve por ref não pode ser utilizado como um valor out ou ref
  • CS1510: Um ref ou out valor deve ser uma variável atribuível

Advertências:

  • CS9191: O ref modificador para o argumento correspondente ao in parâmetro é equivalente a in. Considere usar in em vez disso.
  • CS9192: Argumento deve ser passado com ref ou in palavra-chave.
  • CS9193: Argumento deve ser uma variável porque é passado para um ref readonly parâmetro
  • CS9195: Argumento deve ser passado com a in palavra-chave

Para corrigir estes erros:

  • Armazene o resultado de um acesso a propriedade ou indexador numa variável local antes de a passar como parâmetro de referência. Propriedades e indexadores são métodos que retornam valores em vez de fornecer acesso direto a locais de armazenamento, e os parâmetros de referência requerem uma variável real com uma localização de memória estável que possa ser aliasada (CS0206, CS1510).
  • Use o in modificador em vez de ref ao passar argumentos para in parâmetros. Embora ref tecnicamente funcione devido à compatibilidade retroativa, o in modificador expressa de forma mais clara a intenção de que o argumento é apenas de leitura e pode ser passado de forma mais eficiente como referência sem copiar (CS9191, CS9195).
  • Adicione o modificador de referência apropriado (ref, in, ou ref readonly) ao passar argumentos para parâmetros que esperam referências. Omitir o modificador pode fazer com que o compilador crie uma cópia temporária do valor, o que é ineficiente e pode levar a comportamentos inesperados se o código de chamada esperar que as modificações sejam refletidas na variável original (CS9192, CS9193).

Para mais informações sobre parâmetros de referência e passagem de variáveis por referência, consulte Parâmetros de método, palavra-chave ref e a Especificação da Linguagem C#.

Variáveis de referência graváveis requerem um referente gravável

Uma variável de referência gravável requer que o referente também seja gravável. Os seguintes erros indicam que a variável não é gravável:

  • CS0192: Um readonly campo não pode ser usado como um ref ou out valor (exceto em um construtor)
  • CS0199: Um static readonly campo não pode ser usado como um ref ou out valor (exceto em um construtor estático)
  • CS1605: Não é possível usar variável como um ref ou out valor porque é somente leitura
  • CS1649: Membros de um readonly campo não podem ser usados como um ref ou out valor (exceto em um construtor)
  • CS1651: Campos de um static readonly campo não podem ser usados como um ref ou out valor (exceto em um construtor estático)
  • CS1655: Não é possível usar campos do tipo como um ref ou out valor
  • CS1657: Não é possível usar variável como um ref ou out valor
  • CS8329: Não é possível usar a variável como um ref ou out valor porque é uma variável somente leitura
  • CS8330: Os membros da variável não podem ser usados como valor ref ou out porque é uma variável apenas de leitura
  • CS8331: Não é possível atribuir à variável nem usá-la como o lado direito de uma atribuição ref, porque é uma variável só de leitura
  • CS8332: Não é possível atribuir a um membro de uma variável nem utilizá-lo como lado direito de uma ref operação de atribuição, porque é uma variável só de leitura

Para corrigir estes erros:

  • Copie o valor de um campo só de leitura para uma variável local e passe a variável local como um parâmetro ref ou out. Campos apenas de leitura são imutáveis após a inicialização (exceto dentro dos construtores) e permitir referências graváveis a eles violaria a garantia de imutabilidade que apenas leitura fornece (CS0192, CS0199,CS1649, CS1651).
  • Use ref readonly ou in parâmetros em vez de ref ou out quando precisar de passar variáveis apenas de leitura, variáveis de iteração ou outros valores não graváveis por referência. Estes modificadores indicam que o método só lê o valor referenciado sem tentar modificá-lo. Isso está alinhado com as restrições de imutabilidade da variável original (CS1605,CS1655,CS1657, CS8329).
  • Copie os membros das variáveis de somente leitura para variáveis locais antes de serem passadas como referências graváveis. Embora o próprio membro possa não ser declarado como somente leitura, ele é acedido através de um caminho de somente leitura (via um campo de somente leitura, um parâmetro de in somente leitura ou uma variável local de ref readonly somente leitura), e o compilador impõe a transitividade do estado de somente leitura para evitar mutações indiretas dos dados em somente leitura (CS8330, CS8332).
  • Evite atribuições de ref graváveis a variáveis apenas de leitura, variáveis de iteração foreach, usar recursos de instrução ou variáveis fixas de instruções. Estas variáveis têm semântica de vida especial gerida pelo compilador. A variável é automaticamente finalizada ou descartada no final do seu âmbito. Referências externas criam referências pendentes após a eliminação (CS8331).

Para mais informações sobre semântica de somente leitura e parâmetros de referência, consulte a palavra-chave readonly, o modificador de parâmetro in, o ref readonly e a Especificação da Linguagem C#.