Compartir a través de


Errores y advertencias asociados con parámetros de referencia, variables y devoluciones

Se pueden generar los siguientes errores cuando se trabaja con variables de referencia:

  • CS0192: : un campo readonly no se puede usar como valor de ref o out (excepto en un constructor)
  • CS0199: : un campo static readonly no se puede usar como valor de ref o out (excepto en un constructor)
  • CS0206: es posible que no se use una propiedad o indexador que no devuelva referencias como un valor out o ref
  • CS0631: ref y out no son válidos en este contexto
  • CS0767: no se puede heredar la interfaz con los parámetros de tipo especificados porque hace que el método contenga sobrecargas que solo difieren en ref y out
  • CS1510: un valor ref o out debe ser una variable asignable
  • CS1605: no se puede usar la variable como un valor ref o out porque es de solo lectura
  • CS1623: los iteradores no pueden tener parámetros ref, in o outparámetros
  • CS1649: Miembros de un campo de readonly no se puede usar como valor de ref o out (excepto en un constructor)
  • CS1651: Los campos de un campo estático de solo lectura no se pueden usar como un valor ref o out (excepto en un constructor estático)
  • CS1655: No se pueden usar campos de tipo como ref o outvalor
  • CS1657: no se puede usar la variable como ref o outvalor
  • CS1741: un parámetro ref o out no puede tener un valor predeterminado
  • CS1939: no se puede pasar la variable de intervalo como un parámetro out o ref
  • CS1988: los métodos asincrónicos no pueden tener parámetros ref, in o out
  • CS7084: es posible que un evento de Windows Runtime no se pase como parámetro out o ref.
  • CS8196: Referencia a una variable de salida con tipo implícito no se permite en la misma lista de argumentos.
  • CS8325: 'await' no se puede usar en una expresión que contenga un ref operador condicional
  • CS8326: Ambos valores de operador condicional deben ser valores ref o ninguno de ellos debe ser un valor ref
  • CS8327: la expresión debe ser de tipo correcto para que coincida con el valor ref alternativo
  • CS8329: No se puede usar la variable como un ref valor o out porque es una variable de solo lectura
  • CS8330: los miembros de la variable no se pueden usar como un valor ref o out porque es una variable de solo lectura
  • CS8331: no se puede asignar a la variable ni usarla como el lado derecho de una asignación ref porque es una variable de solo lectura
  • CS8332: No se puede asignar a un miembro de la variable o usarlo como lado derecho de una ref asignación porque es una variable de solo lectura
  • CS8337: el primer parámetro de un método de extensión 'ref' debe ser un tipo de valor o un tipo genérico restringido a struct.
  • CS8338: el primer parámetro 'in' o 'ref readonly' del método de extensión debe ser un tipo de valor concreto (no genérico).
  • CS8373: El lado izquierdo de una asignación de ref debe ser una variable ref.
  • CS8388: Una out variable no se puede declarar como una variable local ref
  • CS8977: No se puede usar "", "refin" o "out" en la firma de un método con atributos "UnmanagedCallersOnly".
  • CS8986: el modificador "scoped" del parámetro no coincide con el destino.
  • CS8987: el modificador "scoped" del parámetro no coincide con el miembro invalidado o implementado.
  • CS9061: El modificador 'scoped' no se puede usar con descarte.
  • CS9062: Los tipos y alias no se pueden denominar "scoped".
  • CS9063: UnscopedRefAttribute no se puede aplicar a este parámetro porque está sin ámbito de forma predeterminada.
  • CS9065: No use "System.Runtime.CompilerServices.ScopedRefAttribute". Use la palabra clave 'scoped' en su lugar.
  • CS9066: UnscopedRefAttribute no se puede aplicar a los parámetros que tienen un modificador "scoped".
  • CS9072: Una variable de deconstrucción no se puede declarar como ref local
  • CS9101: UnscopedRefAttribute solo se puede aplicar a propiedades y métodos de instancia de interfaz virtual y estructura, y no se puede aplicar a constructores o miembros de solo inicialización.
  • CS9102: UnscopedRefAttribute no se puede aplicar a una implementación de interfaz porque el miembro implementado no tiene este atributo.
  • CS9104: no se puede usar un using recurso de instrucción de tipo en métodos asincrónicos ni expresiones lambda asincrónicas.
  • CS9190: readonly el modificador debe especificarse después de ref.
  • CS9199: un parámetro ref readonly no puede tener el atributo Out.

Las siguientes advertencias se generan cuando las variables de referencia se usan incorrectamente:

  • CS9073: el modificador "scoped" del parámetro no coincide con el destino.
  • CS9074: el modificador "scoped" del parámetro no coincide con el miembro invalidado o implementado.
  • CS9191: el modificador ref para el argumento correspondiente al parámetro in es equivalente a in. Considere la posibilidad de usar in en su lugar.
  • CS9192: el argumento debe pasarse con la palabra clave ref o in.
  • CS9193: el argumento debe ser una variable porque se pasa a un ref readonlyparámetro
  • CS9195: El argumento debe pasarse con la in palabra clave
  • CS9196: el modificador de tipo de referencia del parámetro no coincide con el parámetro correspondiente en miembro invalidado o implementado.
  • CS9197: el modificador de tipo de referencia del parámetro no coincide con el parámetro correspondiente en el miembro oculto.
  • CS9198: el modificador de tipo de referencia del parámetro no coincide con el parámetro correspondiente en el destino.
  • CS9200: se especifica un valor predeterminado para el parámetro ref readonly, pero ref readonly solo se debe usar para las referencias. Considere la posibilidad de declarar el parámetro como in.
  • CS9201: El campo Ref debe asignarse antes de su uso.
  • CS9265: el campo nunca se asigna a y siempre tendrá su valor predeterminado (referencia nula)

Estos errores y advertencias siguen estos temas:

En este artículo se usa la variable de referencia de términos como un término general para un parámetro declarado con uno de los modificadores in, ref readonly, ref o out, o una variable local ref, un campo ref en un ref structo un ref devuelto. Una variable de referencia hace referencia a otra variable, denominada referente.

Sintaxis incorrecta

Estos errores indican que está usando una sintaxis incorrecta con respecto a las variables de referencia:

  • CS8373: La parte izquierda de una asignación de ref debe ser una referencia local o un parámetro.
  • CS8388: una out variable no se puede declarar como local ref.
  • CS9190: readonly el modificador debe especificarse después de ref.

Para corregir estos errores:

  • Asegúrate de que el operando izquierdo de un = ref operador es una variable de referencia en lugar de una expresión literal o una variable local no referenciada. La asignación de referencia requiere que ambos lados sean variables de referencia que puedan crear un alias en la misma ubicación de almacenamiento (CS8373).
  • Al declarar parámetros de referencia, escriba el modificador como ref readonly en lugar de readonly ref. La especificación del lenguaje C# requiere que la ref palabra clave preceda al readonly modificador en declaraciones de parámetros para mantener una sintaxis coherente en todos los tipos de parámetros de referencia (CS9190).
  • Utiliza la palabra clave ref en lugar de out al declarar variables de referencia locales. out es exclusivamente un modificador de parámetro que indica que un método debe asignar un valor antes de devolver, mientras que ref es la palabra clave adecuada para crear variables locales que alias otras ubicaciones de almacenamiento (CS8388). Para obtener más información sobre las variables de referencia y sus requisitos de sintaxis, consulte variables de referencia y especificación del lenguaje C#.

Restricciones de variables de referencia

Los siguientes errores indican que no se puede usar una variable de referencia en la que tenga una:

  • CS0631: ref y out no son válidos en este contexto
  • CS0767: no se puede heredar la interfaz con los parámetros de tipo especificados porque hace que el método contenga sobrecargas que solo difieren en ref y out
  • CS1623: los iteradores no pueden tener parámetros ref, in o out
  • CS1741: Un parámetroref o out no puede tener un valor predeterminado
  • CS1939: no se puede pasar la variable de intervalo como un parámetro out o ref
  • CS1988: los métodos asincrónicos no pueden tener parámetros ref, in o out
  • CS7084: es posible que un evento de Windows Runtime no se pase como parámetro out o ref.
  • CS8196: Referencia a una variable out con tipo implícito no se permite en la misma lista de argumentos.
  • CS8325: 'await' no se puede usar en una expresión que contenga un ref operador condicional
  • CS8326: ambos valores de operador condicional deben ser valores ref o ninguno puede ser un valor ref
  • CS8327: la expresión debe ser de tipo correcto para que coincida con el valor ref alternativo
  • CS8337: El primer parámetro de un método de extensión 'ref' debe ser un tipo de valor o un tipo genérico restringido a struct.
  • CS8338: el primer parámetro 'in' o 'ref readonly' del método de extensión debe ser un tipo de valor concreto (no genérico).
  • CS8977: No se puede usar 'ref', 'in', o 'out' en la firma de un método con "UnmanagedCallersOnly".
  • CS9072: Una variable de deconstrucción no se puede declarar como ref local
  • CS9104: no se puede usar un using recurso de instrucción de tipo en métodos asincrónicos ni expresiones lambda asincrónicas.
  • CS9199: Un parámetro ref readonly no puede tener el atributo Out.

Las siguientes advertencias indican que no se debe usar una variable de referencia y podría no ser segura:

  • CS9196: el modificador de tipo de referencia del parámetro no coincide con el parámetro correspondiente en miembro invalidado o implementado.
  • CS9197: el modificador de tipo de referencia del parámetro no coincide con el parámetro correspondiente en el miembro oculto.
  • CS9198: el modificador de tipo de referencia del parámetro no coincide con el parámetro correspondiente en el destino.
  • CS9200: se especifica un valor predeterminado para el parámetro ref readonly, pero ref readonly solo se debe usar para las referencias. Considere la posibilidad de declarar el parámetro como in.
  • CS9201: El campo Ref debe asignarse antes de su uso.
  • CS9265: el campo nunca se asigna a y siempre tendrá su valor predeterminado (referencia nula)

Para corregir estos errores:

  • Quite los parámetros de referencia de los indexadores. Los indexadores están diseñados para proporcionar una sintaxis de acceso similar a la de un array, y el compilador no puede garantizar un seguimiento seguro de la duración de las referencias que se pasan a través de los accesores del indexador (CS0631, CS1623).
  • Quite los parámetros de referencia de los métodos de iterador. Los iteradores ejecutan código perezosamente en varias llamadas mediante máquinas de estado, y el compilador no puede garantizar que las variables referenciadas se mantengan válidas en los límites de 'yield return', donde la ejecución se suspende y luego se reanuda (CS1623).
  • Quite los parámetros de referencia de los métodos asincrónicos. Los métodos asincrónicos pueden suspender la ejecución en puntos await y reanudarse en diferentes subprocesos, lo que hace imposible garantizar que las variables a las que se hace referencia sigan siendo válidas y accesibles durante la ejecución del método (CS1988).
  • Evite usar expresiones await dentro de expresiones condicionales ref. La operación await podría suspender la ejecución e invalidar las referencias seleccionadas por el operador condicional, lo que provocaría un posible uso de referencias invalidadas cuando se reanuda la ejecución (CS8325).
  • Asegúrese de que ambas ramas de un operador condicional ref devuelven referencias o ninguna devuelve una referencia y, cuando ambas son referencias, deben ser del mismo tipo. El operador condicional debe generar un tipo de resultado coherente que el código de llamada pueda usar de forma segura independientemente de la rama seleccionada (CS8326, CS8327).
  • Quite los valores predeterminados de los parámetros ref y out. Los parámetros de referencia siempre deben proporcionarse en el sitio de llamada para establecer la relación de alias necesaria entre el parámetro y una variable existente, lo que hace que los valores predeterminados no sean semánticos (CS1741).
  • Evite declarar una variable con out tipo implícito en una lista de argumentos que también haga referencia a esa misma variable. El compilador debe deducir el tipo de la variable de la firma del método mientras valida simultáneamente los usos de esa variable dentro de la misma expresión, creando una dependencia circular (CS8196).
  • No pase variables de intervalo de consulta LINQ como parámetros de referencia. Las variables de intervalo son variables de iteración generadas por el compilador cuya duración se administra mediante el modelo de ejecución de consultas y no tienen ubicaciones de memoria estables a las que se puede hacer referencia de forma segura (CS1939).
  • Use variables de valor normal en lugar de variables locales ref al deconstruir objetos. Deconstrucción crea nuevas variables para recibir los valores desconstrucidos y las variables de referencia intentarían establecer un alias en estos valores temporales en lugar de almacenarlos de forma independiente (CS9072).
  • Evite implementar varias interfaces en las que los métodos solo difieren en comparación ref con out los modificadores en los parámetros. La especificación del lenguaje C# trata estas como firmas distintas, pero no proporciona una manera de desambiguar qué implementación llamar, ya que ref y out comparten la misma sintaxis de llamada en los puntos de límite de la implementación (CS0767).
  • Quite los parámetros de referencia de los métodos decorados con System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute. Estos métodos se pueden llamar desde código no administrado que no entiende las reglas de seguridad de referencia de C#y no pueden garantizar una administración adecuada de la duración de las variables a las que se hace referencia en el límite administrado o no administrado (CS8977).
  • Use el ref modificador en los primeros parámetros del método de extensión solo para tipos de valor o tipos genéricos restringidos a tipos de valor. Los tipos de referencia ya se pasan por referencia en el nivel de CLR, y agregar ref crearía una referencia a una referencia, mientras que las extensiones de tipo de valor con ref habilitan la mutación de la instancia extendida (CS8337, CS8338).
  • No pase eventos de Windows Runtime como parámetros de referencia. Estos eventos siguen el sistema de tipos de Windows Runtime, que tiene semánticas de duración y de subproceso diferentes a las de las referencias de .NET, y no admite el comportamiento de alias requerido por los parámetros de referencia de C# (CS7084).
  • Quite el System.Runtime.InteropServices.OutAttribute de los parámetros de ref readonly. Este atributo está diseñado para el empaquetado de semánticas en escenarios de invocación de plataforma donde la dirección del parámetro es únicamente de salida, lo que entra en conflicto con la garantía de ref readonly de que el parámetro hace referencia a datos existentes que no se reasignarán (CS9199).
  • Asegúrese de que todos los campos ref de un tipo se asignan en inicializadores de campos o en todas las rutas de código del constructor antes de que el constructor finalice. Los campos de referencia no inicializados contendrán referencias no válidas que podrían provocar daños en la memoria si se accede a ellos (CS9201, CS9265).
  • Haz coincidir los modificadores de referencia (ref, in, out, ref readonly) entre un método y su método base sobrescrito o el método de interfaz implementado. El modificador de referencia forma parte del contrato de firma de método que los tipos derivados deben respetar para mantener la sustituibilidad y las expectativas del llamante (CS9196, CS9197, CS9198).
  • Declare los parámetros como in en lugar de ref readonly al proporcionar valores predeterminados. ref readonly está diseñado para escenarios en los que el autor de la llamada pasa una referencia a una variable existente, mientras que in los parámetros pueden aceptar referencias y copias temporales de valores, haciendo que los valores predeterminados sean significativos (CS9200).

Para obtener más información sobre dónde se permiten las variables de referencia, vea Parámetros de método, Iteradores, patrones de programación asincrónicos y especificación del lenguaje C#.

Restricciones unscoped ref

El calificador unscoped en parámetros ref no se permite en algunas ubicaciones:

  • CS9101: UnscopedRefAttribute solo se puede aplicar a métodos y propiedades de una instancia de estructura o de una interfaz virtual, y no se puede aplicar a constructores o a miembros de solo inicialización.
  • CS9102: UnscopedRefAttribute no se puede aplicar a una implementación de interfaz porque el miembro implementado no tiene este atributo.

Para corregir estos errores:

  • Quite el unscoped modificador o el System.Diagnostics.CodeAnalysis.UnscopedRefAttribute atributo de los constructores de struct y de los miembros de solo inicialización. Estos miembros tienen una semántica de inicialización especial, donde el compilador debe asegurarse de que las referencias no sobrevivan a la fase de inicialización, y permitir referencias sin alcance constituiría una violación de la garantía de que la inicialización se completa antes de que la estructura sea totalmente accesible (CS9101).
  • Quite el modificador unscoped de los métodos de implementación de interfaz cuando el método de la interfaz correspondiente no lo tenga. La característica no delimitada afecta al contrato del método en cuanto a las garantías de duración de las referencias, y las implementaciones deben mantener el mismo contrato que la interfaz que implementan para garantizar que los autores de llamadas puedan confiar en un comportamiento consistente de la duración de las referencias, independientemente de qué implementación se invoque (CS9102).

Para obtener más información sobre las referencias con y sin ámbito, vea Parámetros de método y la especificación de la función mejoras de estructura de bajo nivel.

Las variables de referencia requieren un referente

Debe proporcionar una variable como argumento a un parámetro de referencia, una devolución de referencia o una asignación local ref:

  • CS0206: es posible que no se use una propiedad o indexador que no devuelva referencias como un valor out o ref
  • CS1510: un valor ref o out debe ser una variable asignable

Advertencias:

  • CS9191: el modificador ref para el argumento correspondiente al parámetro in es equivalente a in. Considere la posibilidad de usar in en su lugar.
  • CS9192: el argumento debe pasarse con la palabra clave ref o in.
  • CS9193: el argumento debe ser una variable porque se pasa a un ref readonlyparámetro
  • CS9195: el argumento debe pasarse con la palabra clave in

Para corregir estos errores:

  • Almacene el resultado de un acceso de propiedad o indexador en una variable local antes de pasarlo como parámetro de referencia. Las propiedades y los indexadores son métodos que devuelven valores en lugar de proporcionar acceso directo a las ubicaciones de almacenamiento y los parámetros de referencia requieren una variable real con una ubicación de memoria estable que se puede establecer un alias (CS0206, CS1510).
  • Utilice el in modificador en lugar de ref cuando se pasen argumentos a los in parámetros. Aunque ref técnicamente funciona debido a la compatibilidad con versiones anteriores, el in modificador expresa con más claridad la intención de que el argumento es de solo lectura y puede pasarse de forma más eficaz como referencia sin copiar (CS9191, CS9195).
  • Agregue el modificador de referencia adecuado (ref, ino ref readonly) al pasar argumentos a parámetros que esperan referencias. Omitir el modificador puede hacer que el compilador cree una copia temporal del valor, que es ineficaz y puede provocar un comportamiento inesperado si el código de llamada espera que las modificaciones se reflejen en la variable original (CS9192, CS9193).

Para obtener más información sobre los parámetros de referencia y pasar variables por referencia, vea Parámetros de método, palabra clave ref y especificación del lenguaje C#.

Las variables de referencia grabable requieren un referente grabable

Una variable de referencia grabable requiere que el referente también sea grabable. Los siguientes errores indican que la variable no se puede escribir:

  • CS0192: un campo readonly no se puede usar como un valor ref o out (excepto en un constructor)
  • CS0199: un campo static readonly no se puede usar como un valor ref o out (excepto en un constructor estático)
  • CS1605: no se puede usar una variable como valor ref o out porque es de solo lectura
  • CS1649: los miembros de un campo readonly no se pueden usar como un valor ref o out (excepto en un constructor)
  • CS1651: los campos de un campo static readonly no se puede usar como un valor ref o out (excepto en un constructor estático)
  • CS1655: no se pueden usar campos de tipo como valor ref o out
  • CS1657: no se puede usar una variable como valor ref o out
  • CS8329: no se puede usar la variable como un valor ref o out porque es una variable de solo lectura
  • CS8330: los miembros de la variable no se pueden usar como un valor ref o out porque es una variable de solo lectura
  • CS8331: no se puede asignar a la variable ni usarla como el lado derecho de una asignación ref porque es una variable de solo lectura
  • CS8332: no se puede asignar a un miembro de la variable o usarlo como lado derecho de una asignación ref porque es una variable de solo lectura

Para corregir estos errores:

  • Copie el valor de un campo de solo lectura en una variable local y pase la variable local como ref o out parámetro. Los campos readonly son inmutables después de la inicialización (excepto en constructores) y permitir referencias grabables a ellos infringirían la garantía de inmutabilidad que proporciona readonly (CS0192, CS0199, CS1649, CS1651).
  • Use los parámetros ref readonly o in en lugar de ref o out cuando necesite pasar por referencia variables de solo lectura, variables de iteración u otros valores no grabables. Estos modificadores indican que el método solo leerá el valor al que se hace referencia sin intentar modificarlo. Esto se alinea con las restricciones de inmutabilidad de la variable original (CS1605, CS1655, CS1657, CS8329).
  • Copie miembros de variables de solo lectura en variables locales antes de pasarlos como referencias grabables. Aunque es posible que el propio miembro no se declare como de solo lectura, se tiene acceso a él a través de una ruta de acceso de solo lectura (a través de un campo de solo lectura, in parámetro o ref readonly local), y el compilador exige transitividad de la confidencialidad de lectura para evitar la mutación indirecta de los datos de solo lectura (CS8330, CS8332).
  • Evite asignaciones de referencia grabables para variables de solo lectura, variables de iteración foreach, mediante recursos deinstrucción o variables de instrucción fijas. Estas variables tienen semántica de duración especial administrada por el compilador. La variable se finaliza o elimina automáticamente al final de su ámbito. Las referencias externas crean referencias pendientes después de la eliminación (CS8331).

Para obtener más información sobre la semántica de solo lectura y los parámetros de referencia, vea readonly keyword, in parameter modifier, ref readonly y the C# Language Specification.