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.
You might see the following errors and warnings when you work with reference variables:
- CS0192: A
readonlyfield cannot be used as areforoutvalue (except in a constructor) - CS0199: A
static readonlyfield cannot be used as areforoutvalue (except in a static constructor) - CS0206: A non ref-returning property or indexer may not be used as an
outorrefvalue - CS0631:
refandoutare not valid in this context - CS0767: Cannot inherit interface with the specified type parameters because it causes method to contain overloads which differ only on
refandout - CS1510: A
reforoutvalue must be an assignable variable - CS1605: Cannot use variable as a
reforoutvalue because it is read-only - CS1623: Iterators cannot have
ref,inoroutparameters - CS1649: Members of a
readonlyfield cannot be used as areforoutvalue (except in a constructor) - CS1651: Fields of a static readonly field cannot be used as a
reforoutvalue (except in a static constructor) - CS1655: Cannot use fields of type as a
reforoutvalue - CS1657: Cannot use variable as a
reforoutvalue - CS1741: A
reforoutparameter cannot have a default value - CS1939: Cannot pass the range variable as an
outorrefparameter - CS1988: Async methods cannot have
ref,inoroutparameters - CS7084: A Windows Runtime event may not be passed as an
outorrefparameter. - CS8196: Reference to an implicitly-typed out variable is not permitted in the same argument list.
- CS8325: '
await' cannot be used in an expression containing arefconditional operator - CS8326: Both conditional operator values must be ref values or neither may be a ref value
- CS8327: The expression must be of correct type to match the alternative ref value
- CS8328: The parameter modifier 'modifier' cannot be used with 'modifier'
- CS8329: Cannot use variable as a
reforoutvalue because it is a readonly variable - CS8330: Members of variable cannot be used as a
reforoutvalue because it is a readonly variable - CS8331: Cannot assign to variable or use it as the right hand side of a
refassignment because it is a readonly variable - CS8332: Cannot assign to a member of variable or use it as the right hand side of a
refassignment because it is a readonly variable - CS8337: The first parameter of a '
ref' extension method must be a value type or a generic type constrained to struct. - CS8338: The first '
in' or 'ref readonly' parameter of the extension method must be a concrete (non-generic) value type. - CS8373: The left-hand side of a
refassignment must be a ref variable. - CS8388: An
outvariable cannot be declared as a ref local - CS8977: Cannot use '
ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'. - CS8986: The 'scoped' modifier of parameter 'parameter' doesn't match target 'target'.
- CS8987: The 'scoped' modifier of parameter 'parameter' doesn't match overridden or implemented member.
- CS9061: The 'scoped' modifier cannot be used with discard.
- CS9062: Types and aliases cannot be named 'scoped'.
- CS9063: UnscopedRefAttribute cannot be applied to this parameter because it is unscoped by default.
- CS9065: Do not use 'System.Runtime.CompilerServices.ScopedRefAttribute'. Use the 'scoped' keyword instead.
- CS9066: UnscopedRefAttribute cannot be applied to parameters that have a 'scoped' modifier.
- CS9072: A deconstruction variable cannot be declared as a ref local
- CS9073: The 'scoped' modifier of parameter 'parameter' doesn't match target 'target'.
- CS9074: The 'scoped' modifier of parameter 'parameter' doesn't match overridden or implemented member.
- CS9101: UnscopedRefAttribute can only be applied to struct or virtual interface instance methods and properties, and cannot be applied to constructors or init-only members.
- CS9102: UnscopedRefAttribute cannot be applied to an interface implementation because implemented member doesn't have this attribute.
- CS9104: A
usingstatement resource of type cannot be used in async methods or async lambda expressions. - CS9190:
readonlymodifier must be specified afterref. - CS9191: The
refmodifier for argument corresponding toinparameter is equivalent toin. Consider usingininstead. - CS9192: Argument should be passed with
reforinkeyword. - CS9193: Argument should be a variable because it is passed to a
ref readonlyparameter - CS9195: Argument should be passed with the
inkeyword - CS9196: Reference kind modifier of parameter doesn't match the corresponding parameter in overridden or implemented member.
- CS9197: Reference kind modifier of parameter doesn't match the corresponding parameter in hidden member.
- CS9198: Reference kind modifier of parameter doesn't match the corresponding parameter in target.
- CS9199: A
ref readonlyparameter cannot have the Out attribute. - CS9200: A default value is specified for
ref readonlyparameter, butref readonlyshould be used only for references. Consider declaring the parameter asin. - CS9201: Ref field should be ref-assigned before use.
- CS9265: Field is never ref-assigned to, and will always have its default value (null reference)
- CS9349: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier.
- CS9350: The 'modifier' modifier cannot immediately follow the 'scoped' modifier.
These errors and warnings follow these themes:
- Incorrect syntax: The syntax of your declaration or usage is invalid.
- Language constructs where
refvariables aren't valid: Some C# idioms don't allow variables. Usually this restriction exists because ref safety analysis can't be performed reliably. - Value expression used where a reference variable is needed: The expression used as a reference variable must be a variable, not a value expression.
- Writable reference variables referring to readonly variables: A reference to a readonly variable can't be passed by writable reference.
This article uses the term reference variable as a general term for a parameter declared with one of the in, ref readonly, ref, or out modifiers, or a ref local variable, a ref field in a ref struct, or a ref return. A reference variable refers to another variable, called the referent.
Incorrect syntax
These errors indicate that you're using incorrect syntax for reference variables:
- CS8328: The parameter modifier 'modifier' cannot be used with 'modifier'
- CS8373: The left-hand side of a
refassignment must be a ref variable. - CS8388: An
outvariable cannot be declared as a ref local. - CS9061: The 'scoped' modifier cannot be used with discard.
- CS9062: Types and aliases cannot be named 'scoped'.
- CS9065: Do not use 'System.Runtime.CompilerServices.ScopedRefAttribute'. Use the 'scoped' keyword instead.
- CS9190:
readonlymodifier must be specified afterref. - CS9349: The 'scoped' modifier cannot come after an 'in', 'out', 'ref' or 'readonly' modifier.
- CS9350: The 'modifier' modifier cannot immediately follow the 'scoped' modifier.
To correct these errors:
- Remove or replace one of the incompatible parameter modifiers named in the diagnostic (CS8328). Use only one of
ref,in, orout; don't combineparamswith a reference-passing modifier; and don't useoutfor an extension receiver. Valid compound forms includeref readonlyandscopedfollowed byref,ref readonly,in, orout. - Ensure the left operand of a
= refoperator is a reference variable rather than a value expression or non-reference local. Ref assignment requires both sides to be reference variables that can create an alias to the same storage location (CS8373). - Use the
refkeyword instead ofoutwhen declaring local reference variables.outis exclusively a parameter modifier that indicates a method must assign a value before returning, whereasrefis the appropriate keyword for creating local variables that alias other storage locations (CS8388). - Remove
scopedfrom a discard declaration. A discard doesn't introduce a variable whose lifetime can be restricted (CS9061). - Rename any type or alias named
scoped, or escape the identifier as@scopedwhen that name must be preserved (CS9062). - Replace an explicit
System.Runtime.CompilerServices.ScopedRefAttributeon a parameter with thescopedmodifier (CS9065). - When declaring reference parameters, write the modifier as
ref readonlyrather thanreadonly ref. The C# language specification requires therefkeyword to precede thereadonlymodifier in parameter declarations to maintain consistent syntax across all reference parameter types (CS9190). - When you combine
scopedwith a reference modifier, place it immediately beforeref,in, orout(CS9349, CS9350). For aref readonlyparameter, usescoped ref readonly. - Remove any other modifier immediately after
scoped, or move it to a valid position in the parameter declaration (CS9350). For more information about reference variables and their syntax requirements, see reference variables and the C# Language Specification.
Reference variable restrictions
The following errors and warnings indicate that you can't use a reference variable in a particular context:
- CS0631:
refandoutare not valid in this context - CS0767: Cannot inherit interface with the specified type parameters because it causes method to contain overloads which differ only on
refandout - CS1623: Iterators cannot have
ref,inoroutparameters - CS1741: A
reforoutparameter cannot have a default value - CS1939: Cannot pass the range variable as an
outorrefparameter - CS1988: Async methods cannot have
ref,inoroutparameters - CS7084: A Windows Runtime event may not be passed as an
outorrefparameter. - CS8196: Reference to an implicitly-typed
outvariable is not permitted in the same argument list. - CS8325: 'await' cannot be used in an expression containing a
refconditional operator - CS8326: Both conditional operator values must be ref values or neither may be a ref value
- CS8327: The expression must be of correct type to match the alternative ref value
- CS8337: The first parameter of a '
ref' extension method must be a value type or a generic type constrained to struct. - CS8338: The first '
in' or 'ref readonly' parameter of the extension method must be a concrete (non-generic) value type. - CS8977: Cannot use '
ref', 'in', or 'out' in the signature of a method attributed with 'UnmanagedCallersOnly'. - CS8986: The 'scoped' modifier of parameter 'parameter' doesn't match target 'target'.
- CS8987: The 'scoped' modifier of parameter 'parameter' doesn't match overridden or implemented member.
- CS9072: A deconstruction variable cannot be declared as a ref local
- CS9073: The 'scoped' modifier of parameter 'parameter' doesn't match target 'target'.
- CS9074: The 'scoped' modifier of parameter 'parameter' doesn't match overridden or implemented member.
- CS9104: A
usingstatement resource of type cannot be used in async methods or async lambda expressions. - CS9196: Reference kind modifier of parameter doesn't match the corresponding parameter in overridden or implemented member.
- CS9197: Reference kind modifier of parameter doesn't match the corresponding parameter in hidden member.
- CS9198: Reference kind modifier of parameter doesn't match the corresponding parameter in target.
- CS9199: A
ref readonlyparameter cannot have the Out attribute. - CS9200: A default value is specified for
ref readonlyparameter, butref readonlyshould be used only for references. Consider declaring the parameter asin. - CS9201: Ref field should be ref-assigned before use.
- CS9265: Field is never ref-assigned to, and will always have its default value (null reference)
To correct these errors and warnings:
- Remove reference parameters from indexers. Indexers provide array-like access syntax, and the compiler can't guarantee safe lifetime tracking for references passed through indexer accessors (CS0631, CS1623).
- Remove reference parameters from iterator methods. Iterators execute code lazily across multiple calls using state machines, and the compiler can't ensure referenced variables remain valid across
yield returnboundaries where execution is suspended and resumed (CS1623). - Remove reference parameters from async methods. Async methods might suspend execution at
awaitpoints and resume on different threads, making it impossible to guarantee that referenced variables remain valid and accessible throughout the method's execution (CS1988). - Avoid using await expressions inside ref conditional expressions. The
awaitoperation might suspend execution and invalidate the references being selected by the conditional operator, leading to potential use of invalidated references when execution resumes (CS8325). - Ensure both branches of a ref conditional operator return references or neither returns a reference, and when both are references they must be the same type. The conditional operator must produce a consistent result type that can be safely used by the calling code regardless of which branch is selected (CS8326, CS8327).
- Remove default values from
refandoutparameters. Reference parameters must always be provided at the call site to establish the required aliasing relationship between the parameter and an existing variable, making default values semantically meaningless (CS1741). - Avoid declaring an implicitly typed
outvariable in an argument list that also references that same variable. The compiler must infer the variable's type from the method signature while simultaneously validating uses of that variable within the same expression, creating a circular dependency (CS8196). - Don't pass LINQ query range variables as reference parameters. Range variables are compiler-generated iteration variables whose lifetime is managed by the query execution model and don't have stable memory locations that can be safely referenced (CS1939).
- Use regular value variables instead of ref locals when deconstructing objects. Deconstruction creates new variables to receive the deconstructed values and reference variables would attempt to alias these temporary values rather than store them independently (CS9072).
- Avoid implementing multiple interfaces where methods differ only by
refversusoutmodifiers on parameters. The C# language specification treats these as distinct signatures but doesn't provide a way to disambiguate which implementation to call since bothrefandoutshare the same calling syntax at implementation boundaries (CS0767). - Remove reference parameters from methods decorated with System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute. These methods are callable from unmanaged code that doesn't understand C#'s reference safety rules and can't guarantee proper lifetime management of referenced variables across the managed/unmanaged boundary (CS8977).
- Use the
refmodifier on extension method first parameters only for value types or generic types constrained to value types. Reference types are already passed by reference at the CLR level and addingrefwould create a reference to a reference, while value type extensions withrefenable mutation of the extended instance (CS8337, CS8338). - Don't pass Windows Runtime events as reference parameters. These events follow the Windows Runtime type system, which has different lifetime and threading semantics than .NET references and doesn't support the aliasing behavior required by C# reference parameters (CS7084).
- Remove the System.Runtime.InteropServices.OutAttribute from
ref readonlyparameters. This attribute is designed for marshaling semantics in platform invoke scenarios where the parameter direction is outbound only, which conflicts withref readonly's guarantee that the parameter references existing data that won't be reassigned (CS9199). - Ensure all
reffields in a type are assigned either in field initializers or in all constructor code paths before the constructor completes. Uninitialized ref fields would contain invalid references that could lead to memory corruption if accessed (CS9201, CS9265). - Match the
scopedcharacteristic of every parameter between a lambda or method and its target delegate (CS8986, CS9073), and between an override or implementation and the corresponding member (CS8987, CS9074). The mismatch is an error when both signatures use the current C# 11 ref-safety rules; otherwise, it's a compatibility warning. - Match the reference kind modifiers (
ref,in,out,ref readonly) between a method and its overridden base method or implemented interface method. The reference modifier is part of the method signature contract that derived types must honor to maintain substitutability and caller expectations (CS9196, CS9197, CS9198). - Declare parameters as
inrather thanref readonlywhen providing default values.ref readonlyis designed for scenarios where the caller passes a reference to an existing variable, whereasinparameters can accept both references and temporary copies of values, making default values meaningful (CS9200).
For more information about where reference variables are allowed, see Method parameters, Iterators, Asynchronous programming patterns, and the C# Language Specification.
unscoped ref restrictions
You can't use the unscoped qualifier on ref parameters in some locations:
- CS9063: UnscopedRefAttribute cannot be applied to this parameter because it is unscoped by default.
- CS9066: UnscopedRefAttribute cannot be applied to parameters that have a 'scoped' modifier.
- CS9101: UnscopedRefAttribute can only be applied to struct instance or virtual interface methods and properties, and cannot be applied to constructors or init-only members.
- CS9102: UnscopedRefAttribute cannot be applied to an interface implementation because implemented member doesn't have this attribute.
To correct these errors:
- Remove System.Diagnostics.CodeAnalysis.UnscopedRefAttribute from a parameter that's already unscoped by default (CS9063).
- Remove either the
scopedmodifier or System.Diagnostics.CodeAnalysis.UnscopedRefAttribute so the parameter has one consistent lifetime contract (CS9066). - Remove the
unscopedmodifier or the System.Diagnostics.CodeAnalysis.UnscopedRefAttribute attribute from struct constructors and init-only members. These members have special initialization semantics where the compiler must ensure that any references don't outlive the initialization phase, and allowing unscoped references would violate the guarantee that initialization completes before the struct becomes fully accessible (CS9101). - Remove the
unscopedmodifier from interface implementation methods when the corresponding interface method doesn't have it. The unscoped characteristic affects the method's contract regarding reference lifetime guarantees, and implementations must maintain the same contract as the interface they're implementing to ensure callers can rely on consistent lifetime behavior regardless of which implementation is invoked (CS9102).
For more information about scoped and unscoped references, see Method parameters and Safe context constraint in the C# language specification.
Reference variables require a referent
You must supply a variable as an argument to a reference parameter, reference return, or ref local assignment:
- CS0206: A non ref-returning property or indexer may not be used as an
outorrefvalue - CS1510: A
reforoutvalue must be an assignable variable
Warnings:
- CS9191: The
refmodifier for argument corresponding toinparameter is equivalent toin. Consider usingininstead. - CS9192: Argument should be passed with
reforinkeyword. - CS9193: Argument should be a variable because it is passed to a
ref readonlyparameter - CS9195: Argument should be passed with the
inkeyword
To correct these errors:
- Store the result of a property or indexer access in a local variable before passing it as a reference parameter. Properties and indexers are methods that return values rather than providing direct access to storage locations, and reference parameters require an actual variable with a stable memory location that can be aliased (CS0206, CS1510).
- Use the
inmodifier instead ofrefwhen passing arguments toinparameters. Whilereftechnically works due to backward compatibility, theinmodifier more clearly expresses the intent that the argument is read-only and can be passed more efficiently as a reference without copying (CS9191, CS9195). - Add the appropriate reference modifier (
ref,in, orref readonly) when passing arguments to parameters that expect references. Omitting the modifier might cause the compiler to create a temporary copy of the value, which is inefficient and can lead to unexpected behavior if the calling code expects modifications to be reflected in the original variable (CS9192, CS9193).
For more information about reference parameters and passing variables by reference, see Method parameters, ref keyword, and the C# Language Specification.
Writable reference variables require a writable referent
A writable reference variable requires that the referent is also writable. The following errors indicate that the variable isn't writable:
- CS0192: A
readonlyfield cannot be used as areforoutvalue (except in a constructor) - CS0199: A
static readonlyfield cannot be used as areforoutvalue (except in a static constructor) - CS1605: Cannot use variable as a
reforoutvalue because it is read-only - CS1649: Members of a
readonlyfield cannot be used as areforoutvalue (except in a constructor) - CS1651: Fields of a
static readonlyfield cannot be used as areforoutvalue (except in a static constructor) - CS1655: Cannot use fields of type as a
reforoutvalue - CS1657: Cannot use variable as a
reforoutvalue - CS8329: Cannot use variable as a
reforoutvalue because it is a readonly variable - CS8330: Members of variable cannot be used as a
reforoutvalue because it is a readonly variable - CS8331: Cannot assign to variable or use it as the right hand side of a
refassignment because it is a readonly variable - CS8332: Cannot assign to a member of variable or use it as the right hand side of a
refassignment because it is a readonly variable
To correct these errors:
- Copy the value from a readonly field to a local variable and pass the local variable as a
reforoutparameter. Readonly fields are immutable after initialization (except within constructors) and allowing writable references to them would violate the immutability guarantee that readonly provides (CS0192, CS0199, CS1649, CS1651). - Use
ref readonlyorinparameters instead ofreforoutwhen you need to pass readonly variables, iteration variables, or other non-writable values by reference. These modifiers indicate that the method will only read the referenced value without attempting to modify it. That aligns with the immutability constraints of the original variable (CS1605, CS1655, CS1657, CS8329). - Copy members of readonly variables to local variables before passing them as writable references. Even though the member itself might not be declared as readonly, it's accessed through a readonly path (via a readonly field,
inparameter, orref readonlylocal), and the compiler enforces transitivity of readonly-ness to prevent indirect mutation of readonly data (CS8330, CS8332). - Avoid writable ref assignments to readonly variables, foreach iteration variables, using statement resources, or fixed statement variables. These variables have special lifetime semantics managed by the compiler. The variable is automatically finalized or disposed at the end of its scope. External references create dangling references after disposal (CS8331).
For more information about readonly semantics and reference parameters, see readonly keyword, in parameter modifier, ref readonly, and the C# Language Specification.