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 valor ref ou out (exceto em um construtor)
  • CS0199: um campo static readonly não pode ser usado como um valor ref ou out (exceto em um construtor estático)
  • CS0206: Uma propriedade ou indexador que não retorna referência não pode ser usado como 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 isso faz com que o método contenha sobrecargas que diferem apenas em ref e out
  • CS1510: um valor ref ou out deve ser uma variável atribuível
  • CS1605: não é possível usar a variável como um valor ref ou out porque ela é somente leitura
  • CS1623: os iteradores não podem ter parâmetros ref, in ou out
  • CS1649: os membros de um campo readonly não podem ser usados como um valor ref ou out (exceto em um construtor)
  • CS1651: campos de um campo estático somente leitura não podem ser usados como um valor ref ou out (exceto em um construtor estático)
  • CS1655: não é possível usar campos do tipo como um valor ref ou out
  • CS1657: não é possível usar a variável como um valor ref ou out
  • CS1741: um parâmetro ref ou out não pode ter um valor padrão
  • CS1939: não é possível passar a variável de intervalo como um parâmetro out ou ref
  • CS1988: métodos assíncronos não podem ter parâmetros ref, in ou out
  • CS7084: um evento do Windows Runtime pode não ser passado como um parâmetro out ou ref.
  • 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 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
  • CS8329: não é possível usar a variável como um valor ref ou out porque ela é uma variável somente leitura
  • CS8330: os membros da variável não podem ser usados como um valor ref ou out porque é uma variável somente leitura
  • CS8331: Não é possível atribuir um valor à variável nem usá-la no lado direito de uma atribuição ref porque ela é uma variável somente para 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).
  • 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 uma referência local
  • CS8977: não é possível usar "ref", "in" ou "out" na assinatura de um método atribuído com "UnmanagedCallersOnly".
  • CS8986: O modificador 'com escopo' do parâmetro não corresponde ao destino.
  • CS8987: O modificador 'scoped' do parâmetro não corresponde ao membro substituído ou implementado.
  • CS9061: O modificador 'scoped' não pode ser usado com 'discard'.
  • CS9062: Tipos e aliases não podem ser nomeados 'scoped'.
  • CS9063: UnscopedRefAttribute não pode ser aplicado a este parâmetro porque ele não possui escopo por padrão.
  • CS9065: não use 'System.Runtime.CompilerServices.ScopedRefAttribute'. Em vez disso, use a palavra-chave 'scoped'.
  • CS9066: UnscopedRefAttribute não pode ser aplicado a parâmetros que têm um modificador "com escopo".
  • CS9072: uma variável de desconstrução não pode ser declarada como uma referência local
  • CS9101: UnscopedRefAttribute só pode ser aplicado a métodos e propriedades de instância de struct ou de interface virtual e não pode ser aplicado a construtores nem a membros somente 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 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ós ref.
  • 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:

  • CS9073: O modificador do parâmetro 'com escopo' não corresponde ao alvo.
  • CS9074: o modificador 'scoped' do parâmetro não está em conformidade com o membro substituído ou implementado.
  • CS9191: o modificador ref do argumento correspondente ao parâmetro in é equivalente a in. Considere usar in em vez disso.
  • CS9192: o argumento deve ser passado com a palavra-chave ref ou in.
  • 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, 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 como ref antes de ser usado.
  • CS9265: O campo nunca recebe atribuição por ref e sempre terá seu valor padrão (referência nula)

Estes erros e avisos seguem estes temas:

Este artigo usa o termo variável de referência como termo geral para um parâmetro declarado com um dos modificadores in, ref readonly, ref ou out, ou para uma variável local ref, um campo ref em um ref struct ou um valor de 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ós ref.

Para corrigir estes erros:

  • Verifique se o operando esquerdo de um operador = ref é uma variável de referência, em vez de uma expressão de valor ou uma variável local que não seja de referência. A atribuição ref requer que ambos os lados sejam variáveis de referência que podem 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# requer que a ref palavra-chave preceda o readonly modificador em declarações de parâmetro para manter a sintaxe consistente em todos os tipos de parâmetro de referência (CS9190).
  • Use a palavra-chave ref em vez de out ao 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 retornar, enquanto ref é a palavra-chave apropriada para criar variáveis locais que alias a outros locais de armazenamento (CS8388). Para obter mais informações sobre variáveis de referência e seus requisitos de sintaxe, consulte variáveis de referência e a Especificação da Linguagem C#.

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 em um contexto em que há 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 isso faz com que o método contenha sobrecargas que diferem apenas em ref e out
  • CS1623: iteradores não podem ter parâmetros ref, in ou out
  • CS1741: Um parâmetro ref ou out não pode ter um valor padrão
  • CS1939: não é possível passar a variável de intervalo como um parâmetro out ou ref
  • CS1988: métodos assíncronos não podem ter parâmetros ref, in ou out
  • CS7084: um evento do Windows Runtime pode não ser passado como um parâmetro out ou ref.
  • 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, mas ref readonly deve ser usado apenas para referências. Considere declarar o parâmetro como in.
  • CS9201: Um campo ref deve receber uma atribuição ref antes do uso.
  • CS9265: O campo nunca recebe atribuição por referência e sempre terá seu valor padrão (referência nula)

Para corrigir estes erros:

  • Remova os parâmetros de referência dos indexadores. Os indexadores foram projetados para fornecer sintaxe de acesso semelhante à matriz e o compilador não pode garantir o acompanhamento de tempo de vida seguro para referências passadas por meio de acessadores de indexador (CS0631, CS1623).
  • Remova os parâmetros de referência dos métodos de iterador. Os iteradores executam o código lentamente em várias chamadas usando computadores de estado e o compilador não pode garantir que as variáveis referenciadas permaneçam válidas entre os limites de retorno de rendimento em que a execução é suspensa e retomada (CS1623).
  • Remova os parâmetros de referência dos métodos assíncronos. Os métodos assíncronos podem suspender a execução em pontos de espera e retomar em threads diferentes, 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 de expressões condicionais ref. A operação de espera pode suspender a execução e invalidar as referências selecionadas pelo operador condicional, levando ao uso potencial de referências invalidadas quando a execução for retomada (CS8325).
  • Verifique se ambas as ramificações de um operador condicional ref retornam referências ou não retornam uma referência e, quando ambas são referências, elas devem ser do mesmo tipo. O operador condicional deve produzir um tipo de resultado consistente que possa ser usado com segurança pelo código de chamada, independentemente de qual ramificação esteja selecionada (CS8326, CS8327).
  • Remova os valores padrão dos parâmetros ref e out. Os parâmetros de referência sempre devem ser fornecidos no site de 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 sentido (CS1741).
  • Evite declarar uma variável digitada out implicitamente em uma lista de argumentos que também faça referência à mesma variável. O compilador deve inferir o tipo da variável da assinatura do método ao validar simultaneamente os usos dessa variável na 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 é gerenciado pelo modelo de execução de consulta e não têm locais de memória estáveis que podem ser referenciados com segurança (CS1939).
  • Use variáveis de valor regulares em vez de referências locais ao desconstruir objetos. A desconstrução cria novas variáveis destinadas a receber os valores desconstruídos, e as variáveis de referência tentariam referenciar esses valores temporários em vez de armazená-los individualmente (CS9072).
  • Evite implementar várias interfaces em que os métodos diferem apenas pelos modificadores ref versus out nos parâmetros. A especificação da linguagem C# as trata como assinaturas distintas, mas não fornece uma maneira de desambiguar qual implementação deve ser chamada, pois ambas ref e out compartilham a mesma sintaxe de chamada nos limites de implementação (CS0767).
  • Remover parâmetros de referência de métodos decorados com System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute. Esses métodos podem ser chamados a partir de código não gerenciado que não entende as regras de segurança de referência do C# e não podem garantir o gerenciamento adequado do tempo de vida de variáveis referenciadas no limite gerenciado/não gerenciado (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 no nível CLR e adicionar ref criaria uma referência a uma referência, enquanto as extensões de tipo de valor com ref habilitam a mutação da instância estendida (CS8337, CS8338).
  • Não passe eventos do Windows Runtime como parâmetros de referência. Esses eventos seguem o sistema de tipos do Windows Runtime, que tem semântica de tempo de vida e threading diferente das referências do .NET e não dá suporte ao comportamento de aliasing exigido pelos parâmetros de referência C# (CS7084).
  • Remova o System.Runtime.InteropServices.OutAttribute dos parâmetros ref readonly. Esse atributo foi projetado para marshaling de semântica em cenários de invocação de plataforma em que a direção do parâmetro é somente de saída, o que entra em conflito com a garantia de que o parâmetro se refere aos dados existentes que não serão reatribuídos (ref readonly).
  • Certifique-se de que todos os ref campos de um tipo sejam atribuídos, quer em inicializadores de campo, quer em todos os caminhos de código do construtor antes que o construtor seja concluído. Campos ref não inicializados conteriam referências inválidas que poderiam levar à corrupção de memória se acessadas (CS9201, CS9265).
  • Corresponda aos modificadores de tipo de referência (ref, in, out, ref readonly) entre um método e seu método base substituído ou método de interface implementado. O modificador de referência faz parte do contrato da assinatura de método que os tipos derivados devem respeitar para manter a substituibilidade e atender às expectativas do chamador (CS9196, CS9197, CS9198).
  • Declare parâmetros como in em vez de ref readonly ao fornecer valores padrão. ref readonly é projetado para cenários em que o chamador passa uma referência a uma variável existente, enquanto in os parâmetros podem aceitar referências e cópias temporárias de valores, tornando os valores padrão significativos (CS9200).

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

Restrições unscoped ref

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

  • CS9101: UnscopedRefAttribute aplica-se apenas a métodos e propriedades de instâncias de struct ou interfaces virtuais e não pode ser aplicado a construtores ou membros apenas 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.

Para corrigir estes erros:

  • Remova o modificador unscoped ou o atributo System.Diagnostics.CodeAnalysis.UnscopedRefAttribute dos construtores de struct e membros somente de inicialização. Esses membros têm semântica especial de inicialização, em que o compilador deve garantir que nenhuma referência sobreviva à fase de inicialização, e permitir referências sem escopo violaria a garantia de que a inicialização é concluída antes que a estrutura se torne totalmente acessível (CS9101).
  • Remova o unscoped modificador dos métodos de implementação da interface quando o método de interface correspondente não o tiver. A característica não restrita afeta o contrato do método em relação às garantias do ciclo de vida de referência, e as implementações devem manter o mesmo contrato que a interface que estão implementando, para garantir que os chamadores possam contar com um comportamento consistente de ciclo de vida, independentemente de qual implementação seja invocada (CS9102).

Para obter mais informações sobre referências com escopo e sem escopo, consulte parâmetros de método e restrição de contexto seguro na especificação da linguagem C#.

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 ou ref
  • CS1510: O valor ref ou out deve ser uma variável atribuível

Avisos:

  • CS9191: O modificador ref do argumento correspondente ao parâmetro in é equivalente a in. Considere usar in em vez disso.
  • CS9192: o argumento deve ser passado com a palavra-chave ref ou in.
  • 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

Para corrigir estes erros:

  • Armazene o resultado de um acesso de propriedade ou indexador em uma variável local antes de passá-lo como um 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 parâmetros de referência exigem uma variável real com um local de memória estável que pode ser aliased (CS0206, CS1510).
  • Use o modificador in em vez do ref ao passar argumentos para parâmetros in. Embora ref tecnicamente funcione devido à compatibilidade com versões anteriores, o in modificador expressa mais claramente a intenção de que o argumento seja somente leitura e possa ser passado com mais eficiência como uma referência sem copiar (CS9191, CS9195).
  • Adicione o modificador de referência apropriado (refou inref 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, que é ineficiente e pode levar a um comportamento inesperado se o código de chamada espera que as modificações sejam refletidas na variável original (CS9192, CS9193).

Para obter mais informações sobre parâmetros de referência e variáveis de passagem 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 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 valor ref ou out (exceto em um construtor)
  • CS0199: um campo static readonly não pode ser usado como um valor ref ou out (exceto em um construtor estático)
  • CS1605: não é possível usar a variável como um valor ref ou out porque ela é somente leitura
  • CS1649: os membros de um campo readonly não podem ser usados como um valor ref ou out (exceto em um construtor)
  • CS1651: campos de um campo static readonly não podem ser usados como um valor ref ou out (exceto em um construtor estático)
  • CS1655: não é possível usar campos do tipo como um valor ref ou out
  • CS1657: não é possível usar variável como um valor ref ou out
  • CS8329: não é possível usar a variável como um valor ref ou out porque ela é uma variável somente leitura
  • CS8330: os membros da variável não podem ser usados como um valor ref ou out porque é uma variável somente leitura
  • CS8331: não é possível atribuir à variável nem usá-la no lado direito de uma atribuição ref porque ela é uma variável somente leitura
  • CS8332: não é possível atribuir a um membro de uma variável nem usá-la no lado direito de uma atribuição ref porque ela é uma variável somente para leitura

Para corrigir estes erros:

  • Copie o valor de um campo readonly para uma variável local e passe a variável local como um ref ou out parâmetro. Os campos readonly são imutáveis após a inicialização (exceto nos construtores) e permitir referências graváveis a eles violaria a garantia de imutabilidade que readonly fornece (CS0192, CS0199, CS1649, CS1651).
  • Use ref readonly ou in parâmetros em vez de ref ou out quando precisar passar variáveis de leitura, variáveis de iteração ou outros valores não graváveis por referência. Esses modificadores indicam que o método lerá apenas o valor referenciado sem tentar modificá-lo. Isso se alinha às restrições de imutabilidade da variável original (CS1605, CS1655, CS1657, CS8329).
  • Copie membros de variáveis somente leitura para variáveis locais antes de passá-los como referências graváveis. Embora o próprio membro possa não ser declarado como readonly, ele é acessado por meio de um caminho readonly (por meio de um campo readonly, in parâmetro ou ref readonly local), e o compilador impõe a transitividade do readonly, para evitar mutação indireta de dados readonly (CS8330, CS8332).
  • Evite atribuições ref graváveis para variáveis readonly, variáveis de iteração foreach, usando recursos de instrução ou variáveis de instrução fixa. Essas variáveis têm semântica de tempo de vida especial gerenciada pelo compilador. A variável é finalizada ou descartada automaticamente no final de seu escopo. Referências externas criam referências pendentes após o descarte (CS8331).

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