Tipos de estructura ref (referencia de C#)

Puede usar el modificador ref en la declaración de un tipo de estructura. Las instancias de un tipo ref struct se asignan en la pila y no pueden escapar al montón administrado. Para asegurarse de esto, el compilador limita el uso de tipos ref struct de la siguiente manera:

  • ref struct no puede ser el tipo de elemento de una matriz.
  • ref struct no puede ser un tipo declarado de un campo de una clase o un elemento que no sea ref struct.
  • ref struct no puede implementar interfaces.
  • A ref struct no se le puede aplicar la conversión boxing a System.ValueType ni System.Object.
  • ref struct no puede ser un argumento de tipo.
  • Una variable de ref struct no se puede capturar con una expresión lambda ni una función local.
  • Una variable de ref struct no se puede usar en un método async. Sin embargo, puede usar variables de ref struct en métodos sincrónicos, como los que devuelven Task o Task<TResult>.
  • Una variable de ref struct no se puede usar en iteradores.

Puede definir un elemento ref struct descartable. Para ello, asegúrese de que el elemento ref struct se ajuste al patrón descartable. Es decir, tiene una instancia o un método Dispose de extensión, que es accesible, no tiene parámetros y tiene un tipo de valor devuelto void. Puede usar la instrucción using o declaración con una instancia de un elemento descartable ref struct.

Normalmente, se define un tipo ref struct cuando se necesita un tipo que también incluya miembros de datos de tipos ref struct:

public ref struct CustomRef
{
    public bool IsValid;
    public Span<int> Inputs;
    public Span<int> Outputs;
}

Para declarar ref struct como readonly, combine los modificadores readonly y ref en la declaración de tipos (el modificador readonly debe ir delante del modificador ref):

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; }
}

En .NET, System.Span<T> y System.ReadOnlySpan<T> son ejemplos de una clase ref struct.

Campos ref

A partir de C# 11, puede declarar un campo ref en un elemento ref struct, como se muestra en el siguiente ejemplo:

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;
    }
}

Un campo ref puede tener el valor null. Use el método Unsafe.IsNullRef<T>(T) para determinar si un campo ref es null.

Puede aplicar el modificador readonly a un campo ref de varias formas:

  • readonly ref: puede aplicar una asignación de referencia al campo con el operador = ref solo dentro de un constructor o un descriptor de acceso init. Puede asignar un valor con el operador = en cualquier punto permitido por el modificador de acceso del campo.
  • ref readonly: no se puede asignar un valor con el operador = al campo en ningún momento. Sin embargo, puede aplicar una asignación de referencia a un campo con el operador = ref.
  • readonly ref readonly: solo puede aplicar una asignación de referencia a un campo en un constructor o un descriptor de acceso init. No puede asignar un valor al campo en ningún momento.

El compilador se asegura de que una referencia almacenada en un campo ref no sobreviva al valor al que hace referencia.

La característica de campos ref permite una implementación segura de tipos como System.Span<T>:

public readonly ref struct Span<T>
{
    internal readonly ref T _reference;
    private readonly int _length;

    // Omitted for brevity...
}

El tipo Span<T> almacena una referencia a través de la cual accede a los elementos contiguos en memoria. El uso de una referencia permite a una instancia Span<T> evitar copiar el almacenamiento al que hace referencia.

Especificación del lenguaje C#

Para más información, vea las secciones siguientes de la Especificación del lenguaje C#:

Para obtener más información sobre los campos ref, consulte la nota de propuesta de mejoras de estructura de bajo nivel.

Consulte también