Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The following errors can occur when you violate reference variable safety rules:
- CS8166: Cannot return a parameter by reference because it is not a
refparameter - CS8167: Cannot return by reference a member of parameter because it is not a
reforoutparameter - CS8168: Cannot return local by reference because it is not a ref local
- CS8169: Cannot return a member of local variable by reference because it is not a ref local
- CS8345: Field or auto-implemented property cannot be of type unless it is an instance member of a
ref struct. - CS8348: Cannot use a member of result of 'member' in this context because it may expose variables referenced by parameter 'parameter name' outside of their declaration scope
- CS8349: Expression cannot be used in this context because it may indirectly expose variables outside of their declaration scope
- CS8350: This combination of arguments to 'member' is disallowed because it may expose variables referenced by parameter 'parameter name' outside of their declaration scope
- CS8351: Branches of a
refconditional operator cannot refer to variables with incompatible declaration scopes - CS8374: Cannot ref-assign source has a narrower escape scope than destination.
- CS9075: Cannot return a parameter by reference because it is scoped to the current method
- CS9076: Cannot return by reference a member of parameter because it is scoped to the current method
- CS9077: Cannot return a parameter by reference through a
refparameter; it can only be returned in a return statement - CS9078: Cannot return by reference a member of parameter through a
refparameter; it can only be returned in a return statement - CS9079: Cannot ref-assign source to destination because source can only escape the current method through a return statement.
- CS9096: Cannot ref-assign source to destination because source has a wider value escape scope than destination allowing assignment through destination of values with narrower escapes scopes than source.
The following warnings can occur when you violate reference variable safety rules:
- CS9080: Use of variable in this context may expose referenced variables outside of their declaration scope
- CS9081: A result of a stackalloc expression of type in this context may be exposed outside of the containing method
- CS9082: Local is returned by reference but was initialized to a value that cannot be returned by reference
- CS9083: A member is returned by reference but was initialized to a value that cannot be returned by reference
- CS9084: Struct member returns 'this' or other instance members by reference
- CS9085: This ref-assigns source to destination but source has a narrower escape scope than destination.
- CS9086: The branches of the ref conditional operator refer to variables with incompatible declaration scopes
- CS9087: This returns a parameter by reference but it is not a
refparameter - CS9088: This returns a parameter by reference but it is scoped to the current method
- CS9089: This returns by reference a member of parameter that is not a
reforoutparameter - CS9090: This returns by reference a member of parameter that is scoped to the current method
- CS9091: This returns local by reference but it is not a ref local
- CS9092: This returns a member of local by reference but it is not a ref local
- CS9093: This ref-assigns source to destination but source can only escape the current method through a return statement.
- CS9094: This returns a parameter by reference through a
refparameter; but it can only safely be returned in a return statement - CS9095: This returns by reference a member of parameter through a
refparameter; but it can only safely be returned in a return statement - CS9097: This ref-assigns source to destination but source has a wider value escape scope than destination allowing assignment through destination of values with narrower escapes scopes than source.
Returning references with incompatible scopes
The compiler prevents you from returning a reference to a variable when the variable's lifetime doesn't extend beyond the method's scope. These errors occur when you try to return by reference a parameter, local variable, or member that you didn't declare with ref or that has a scope limited to the current method.
Errors:
- CS8166: Cannot return a parameter by reference because it is not a
refparameter - CS8167: Cannot return by reference a member of parameter because it is not a
reforoutparameter - CS8168: Cannot return local by reference because it is not a ref local
- CS8169: Cannot return a member of local variable by reference because it is not a ref local
- CS9075: Cannot return a parameter by reference because it is scoped to the current method
- CS9076: Cannot return by reference a member of parameter because it is scoped to the current method
- CS9077: Cannot return a parameter by reference through a
refparameter; it can only be returned in a return statement - CS9078: Cannot return by reference a member of parameter through a
refparameter; it can only be returned in a return statement
Warnings:
- CS9087: This returns a parameter by reference but it is not a
refparameter - CS9088: This returns a parameter by reference but it is scoped to the current method
- CS9089: This returns by reference a member of parameter that is not a
reforoutparameter - CS9090: This returns by reference a member of parameter that is scoped to the current method
- CS9091: This returns local by reference but it is not a ref local
- CS9092: This returns a member of local by reference but it is not a ref local
- CS9094: This returns a parameter by reference through a
refparameter; but it can only safely be returned in a return statement - CS9095: This returns by reference a member of parameter through a
refparameter; but it can only safely be returned in a return statement
To resolve these errors:
- Change the method signature to declare parameters with the
refkeyword instead of passing them by value. This change allows you to return the parameter's storage location safely because the caller controls the variable's lifetime (CS8166, CS8167, CS9087, CS9089). - For local variables, declare them as
reflocals by assigning them from a ref-returning expression or a ref parameter. This change ensures the local refers to storage with a sufficient lifetime rather than creating a new variable with method-scoped lifetime (CS8168, CS8169, CS9091, CS9092). - When you declare a parameter with the
scopedmodifier, avoid returning it by reference. Thescopedmodifier explicitly restricts the parameter's reference from escaping the method, preventing potential dangling references (CS9075, CS9076, CS9088, CS9090). - If you need to return a reference that comes from a
refparameter, use a directreturn refstatement rather than assigning the reference to anotherrefparameter and returning that reference. The compiler can only track the escape scope through direct return statements (CS9077, CS9078, CS9094, CS9095).
For more information about ref safety rules, see the article on ref returns and the C# standard section on ref safe contexts.
Ref assignments with incompatible scopes
The compiler prevents ref assignment operations where the source variable has a narrower escape scope than the destination. A ref assignment creates a reference from the destination to the source's storage location. If the source goes out of scope before the destination, the destination refers to invalid memory.
Errors:
- CS8374: Cannot ref-assign source has a narrower escape scope than destination.
- CS9079: Cannot ref-assign source to destination because source can only escape the current method through a return statement.
- CS9096: Cannot ref-assign source to destination because source has a wider value escape scope than destination allowing assignment through destination of values with narrower escapes scopes than source.
Warnings:
- CS9085: This ref-assigns source to destination but source has a narrower escape scope than destination.
- CS9093: This ref-assigns source to destination but source can only escape the current method through a return statement.
- CS9097: This ref-assigns source to destination but source has a wider value escape scope than destination allowing assignment through destination of values with narrower escapes scopes than source.
To resolve these errors:
- Restructure your code so that the source variable in a ref assignment has an escape scope at least as wide as the destination variable. This change ensures the destination reference remains valid for its entire lifetime and prevents dangling references (CS8374, CS9085).
- When a variable can only escape the method through a return statement, don't assign it to
refvariables accessed through other means. Examples include storing in fields or returning through ref parameters. Those actions violate the restriction that the source can only be used in return statements (CS9079, CS9093). - For ref assignments involving value escape scopes, ensure the source's value escape scope isn't wider than the destination's. A mismatch would allow you to assign narrower-scoped values through the destination reference, potentially creating references to short-lived values (CS9096, CS9097).
For more information about ref safety rules, see the article on ref returns and the C# standard section on ref safe contexts.
Escape scope violations and conditional operators
The compiler tracks how variables can escape their declaration scope through various operations. These errors occur when you use variables in contexts that could expose referenced variables outside their valid lifetime, including ref conditional operators and stackalloc expressions.
Errors:
- CS8348: Cannot use a member of result of 'member' in this context because it may expose variables referenced by parameter 'parameter name' outside of their declaration scope
- CS8349: Expression cannot be used in this context because it may indirectly expose variables outside of their declaration scope
- CS8350: This combination of arguments to 'member' is disallowed because it may expose variables referenced by parameter 'parameter name' outside of their declaration scope
- CS8351: Branches of a
refconditional operator cannot refer to variables with incompatible declaration scopes
Warnings:
- CS9080: Use of variable in this context may expose referenced variables outside of their declaration scope
- CS9081: A result of a stackalloc expression of type in this context may be exposed outside of the containing method
- CS9086: The branches of the ref conditional operator refer to variables with incompatible declaration scopes
To resolve these errors:
- For a member access on a call result or another expression that can carry references, don't use the value in a context where those references could outlive the parameter or local from which they were derived. Depending on the API contract, keep the use within its safe scope, pass storage with a sufficiently wide lifetime, or change the API signature, such as adding
scopedto a parameter when the method doesn't allow its references to escape (CS8348, CS8349). - For a disallowed combination of call arguments, ensure that an argument with a narrower safe scope can't be stored in another argument or the receiver with a wider scope. Depending on the API contract, use arguments with compatible lifetimes, separate the operations, or add an appropriate
scopedmodifier to a parameter that doesn't allow references to escape (CS8350). - Modify the
refconditional operator (the?:operator withrefreturns) so that both the true and false branches refer to variables that have compatible declaration scopes. Both variables must have lifetimes that extend to at least the same scope level, preventing the conditional expression from potentially returning a reference that becomes invalid (CS8351, CS9086). - When using variables in expressions or method calls, ensure the context doesn't allow referenced variables to escape beyond their declaration scope. Typically, avoid passing scoped variables to methods or expressions where they might be captured or stored beyond their intended lifetime (CS9080).
- For
stackallocexpressions, avoid assigning the result to variables or using it in contexts where the stack-allocated memory could be accessed outside the containing method. The method automatically frees stack-allocated memory when it returns, and accessing it afterward results in undefined behavior (CS9081).
For more information, see the article on ref returns, the article on memory usage, and the C# standard section on ref safe contexts.
Struct member and field restrictions
The compiler enforces special rules for struct members and fields to prevent dangling references. These errors occur when struct members return references to instance state or when fields have types that require special handling.
Errors:
- CS8345: Field or auto-implemented property cannot be of type unless it is an instance member of a
ref struct.
Warnings:
- CS9082: Local is returned by reference but was initialized to a value that cannot be returned by reference
- CS9083: A member is returned by reference but was initialized to a value that cannot be returned by reference
- CS9084: Struct member returns 'this' or other instance members by reference
To resolve these errors:
- Ensure that fields and auto-implemented properties with ref-like types (such as
Span<T>orref structtypes) are only declared as instance members within a ref struct rather than in regular structs or classes, because ref-like types can only safely exist on the stack and ref structs provide the necessary lifetime guarantees (CS8345). - When returning a local variable by reference from a method, verify that the local was initialized from a source that has a sufficient escape scope such as a ref parameter or ref-returning method call, rather than from a value-typed expression or local-scoped variable that would create a reference to short-lived storage (CS9082, CS9083).
- In struct instance methods or properties, avoid returning
thisor any instance fields by reference, because structs are value types that are often copied, and returning a reference to an instance member could create a reference to a temporary copy destroyed after the method returns (CS9084).
For more information, see the article on ref struct types and the C# standard section on ref safe contexts.