Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Se pueden generar los siguientes errores cuando se trabaja con variables de referencia:
-
CS0192: : un campo
readonlyno se puede usar como valor derefoout(excepto en un constructor) -
CS0199: : un campo
static readonlyno se puede usar como valor derefoout(excepto en un constructor) -
CS0206: es posible que no se use una propiedad o indexador que no devuelva referencias como un valor
outoref -
CS0631:
refyoutno 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
refyout -
CS1510: un valor
refooutdebe ser una variable asignable -
CS1605: no se puede usar la variable como un valor
refooutporque es de solo lectura -
CS1623: los iteradores no pueden tener parámetros
ref,inooutparámetros -
CS1649: Miembros de un campo de
readonlyno se puede usar como valor derefoout(excepto en un constructor) -
CS1651: Los campos de un campo estático de solo lectura no se pueden usar como un valor
refoout(excepto en un constructor estático) -
CS1655: No se pueden usar campos de tipo como
refooutvalor -
CS1657: no se puede usar la variable como
refooutvalor -
CS1741: un parámetro
refooutno puede tener un valor predeterminado -
CS1939: no se puede pasar la variable de intervalo como un parámetro
outoref -
CS1988: los métodos asincrónicos no pueden tener parámetros
ref,inoout -
CS7084: es posible que un evento de Windows Runtime no se pase como parámetro
outoref. - 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 unrefoperador 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
refvalor ooutporque es una variable de solo lectura -
CS8330: los miembros de la variable no se pueden usar como un valor
refooutporque es una variable de solo lectura -
CS8331: no se puede asignar a la variable ni usarla como el lado derecho de una asignación
refporque es una variable de solo lectura -
CS8332: No se puede asignar a un miembro de la variable o usarlo como lado derecho de una
refasignació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
refdebe ser una variable ref. -
CS8388: Una
outvariable 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
usingrecurso de instrucción de tipo en métodos asincrónicos ni expresiones lambda asincrónicas. -
CS9190:
readonlyel modificador debe especificarse después deref. -
CS9199: un parámetro
ref readonlyno 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
refpara el argumento correspondiente al parámetroines equivalente ain. Considere la posibilidad de usarinen su lugar. -
CS9192: el argumento debe pasarse con la palabra clave
refoin. -
CS9193: el argumento debe ser una variable porque se pasa a un
ref readonlyparámetro -
CS9195: El argumento debe pasarse con la
inpalabra 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, peroref readonlysolo se debe usar para las referencias. Considere la posibilidad de declarar el parámetro comoin. - 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:
- Sintaxis incorrecta: la sintaxis de la declaración o el uso no es válida.
-
Construcciones de lenguaje en
reflas que las variables no son válidas: algunas expresiones de C# no permiten variables. Normalmente esto se debe a que el análisis de seguridad ref no se puede realizar de forma confiable. - Expresión de valor que se usa cuando se necesita una variable de referencia: la expresión usada como variable de referencia debe ser una variable, no una expresión de valor.
- Variables de referencia grabables que hacen referencia a variables de solo lectura: una referencia a una variable readonly no se puede pasar mediante referencia grabable.
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
refdebe ser una referencia local o un parámetro. -
CS8388: una
outvariable no se puede declarar como local ref. -
CS9190:
readonlyel modificador debe especificarse después deref.
Para corregir estos errores:
- Asegúrate de que el operando izquierdo de un
= refoperador 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 readonlyen lugar dereadonly ref. La especificación del lenguaje C# requiere que larefpalabra clave preceda alreadonlymodificador en declaraciones de parámetros para mantener una sintaxis coherente en todos los tipos de parámetros de referencia (CS9190). - Utiliza la palabra clave
refen lugar deoutal declarar variables de referencia locales.outes exclusivamente un modificador de parámetro que indica que un método debe asignar un valor antes de devolver, mientras querefes 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:
refyoutno 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
refyout -
CS1623: los iteradores no pueden tener parámetros
ref,inoout -
CS1741: Un parámetro
refooutno puede tener un valor predeterminado -
CS1939: no se puede pasar la variable de intervalo como un parámetro
outoref -
CS1988: los métodos asincrónicos no pueden tener parámetros
ref,inoout -
CS7084: es posible que un evento de Windows Runtime no se pase como parámetro
outoref. -
CS8196: Referencia a una variable
outcon 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
refoperador 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
usingrecurso de instrucción de tipo en métodos asincrónicos ni expresiones lambda asincrónicas. -
CS9199: Un parámetro
ref readonlyno 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, peroref readonlysolo se debe usar para las referencias. Considere la posibilidad de declarar el parámetro comoin. - 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
refyout. 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
outtipo 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
refconoutlos 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 querefyoutcomparten 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
refmodificador 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 agregarrefcrearía una referencia a una referencia, mientras que las extensiones de tipo de valor conrefhabilitan 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 deref readonlyde que el parámetro hace referencia a datos existentes que no se reasignarán (CS9199). - Asegúrese de que todos los campos
refde 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
inen lugar deref readonlyal proporcionar valores predeterminados.ref readonlyestá diseñado para escenarios en los que el autor de la llamada pasa una referencia a una variable existente, mientras queinlos 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
unscopedmodificador 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
unscopedde 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
outoref -
CS1510: un valor
refooutdebe ser una variable asignable
Advertencias:
-
CS9191: el modificador
refpara el argumento correspondiente al parámetroines equivalente ain. Considere la posibilidad de usarinen su lugar. -
CS9192: el argumento debe pasarse con la palabra clave
refoin. -
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
inmodificador en lugar derefcuando se pasen argumentos a losinparámetros. Aunquereftécnicamente funciona debido a la compatibilidad con versiones anteriores, elinmodificador 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,inoref 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
readonlyno se puede usar como un valorrefoout(excepto en un constructor) -
CS0199: un campo
static readonlyno se puede usar como un valorrefoout(excepto en un constructor estático) -
CS1605: no se puede usar una variable como valor
refooutporque es de solo lectura -
CS1649: los miembros de un campo
readonlyno se pueden usar como un valorrefoout(excepto en un constructor) -
CS1651: los campos de un campo
static readonlyno se puede usar como un valorrefoout(excepto en un constructor estático) -
CS1655: no se pueden usar campos de tipo como valor
refoout -
CS1657: no se puede usar una variable como valor
refoout -
CS8329: no se puede usar la variable como un valor
refooutporque es una variable de solo lectura -
CS8330: los miembros de la variable no se pueden usar como un valor
refooutporque es una variable de solo lectura -
CS8331: no se puede asignar a la variable ni usarla como el lado derecho de una asignación
refporque 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
refporque 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
refooutpará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 readonlyoinen lugar derefooutcuando 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,
inparámetro oref readonlylocal), 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.