ref
structure types (C# reference)
You can use the ref
modifier in the declaration of a structure type. Instances of a ref struct
type are allocated on the stack and can't escape to the managed heap. To ensure that, the compiler limits the usage of ref struct
types as follows:
- A
ref struct
can't be the element type of an array. - A
ref struct
can't be a declared type of a field of a class or a non-ref struct
. - A
ref struct
can't implement interfaces. - A
ref struct
can't be boxed to System.ValueType or System.Object. - A
ref struct
can't be a type argument. - A
ref struct
variable can't be captured by a lambda expression or a local function. - A
ref struct
variable can't be used in anasync
method. However, you can useref struct
variables in synchronous methods, for example, in methods that return Task or Task<TResult>. - A
ref struct
variable can't be used in iterators.
You can define a disposable ref struct
. To do that, ensure that a ref struct
fits the disposable pattern. That is, it has an instance Dispose
method, which is accessible, parameterless and has a void
return type. You can use the using statement or declaration with an instance of a disposable ref struct
.
Typically, you define a ref struct
type when you need a type that also includes data members of ref struct
types:
public ref struct CustomRef
{
public bool IsValid;
public Span<int> Inputs;
public Span<int> Outputs;
}
To declare a ref struct
as readonly
, combine the readonly
and ref
modifiers in the type declaration (the readonly
modifier must come before the ref
modifier):
public readonly ref struct ConversionRequest
{
public ConversionRequest(double rate, ReadOnlySpan<double> values)
{
Rate = rate;
Values = values;
}
public double Rate { get; }
public ReadOnlySpan<double> Values { get; }
}
In .NET, examples of a ref struct
are System.Span<T> and System.ReadOnlySpan<T>.
ref
fields
Beginning with C# 11, you can declare a ref
field in a ref struct
, as the following example shows:
public ref struct RefFieldExample
{
private ref int number;
public int GetNumber()
{
if (System.Runtime.CompilerServices.Unsafe.IsNullRef(ref number))
{
throw new InvalidOperationException("The number ref field is not initialized.");
}
return number;
}
}
A ref
field may have the null
value. Use the Unsafe.IsNullRef<T>(T) method to determine if a ref
field is null
.
You can apply the readonly
modifier to a ref
field in the following ways:
readonly ref
: You can ref reassign such a field with the= ref
operator only inside a constructor or aninit
accessor. You can assign a value with the=
operator at any point allowed by the field access modifier.ref readonly
: At any point, you cannot assign a value with the=
operator to such a field. However, you can ref reassign a field with the= ref
operator.readonly ref readonly
: You can only ref reassign such a field in a constructor or aninit
accessor. At any point, you cannot assign a value to the field.
The compiler ensures that a reference stored in a ref
field doesn't outlive its referent.
The ref
fields feature enables a safe implementation of types like System.Span<T>:
public readonly ref struct Span<T>
{
internal readonly ref T _reference;
private readonly int _length;
// Omitted for brevity...
}
The Span<T>
type stores a reference through which it accesses the contiguous elements in memory. The use of a reference enables a Span<T>
instance to avoid copying the storage it refers to.
C# language specification
For more information, see the following sections of the C# language specification:
For more information about ref
fields, see the Low-level struct improvements proposal note.
See also
Feedback
https://aka.ms/ContentUserFeedback.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see:Submit and view feedback for