ref Типы структур (справочник по C#)

Модификатор можно использовать ref в объявлении типа структуры. Экземпляры ref struct типа выделяются в стеке и не могут экранироваться в управляемую кучу. Чтобы убедиться, что компилятор ограничивает использование ref struct типов следующим образом:

  • Не ref struct может быть типом элемента массива.
  • Не ref struct может быть объявленным типом поля класса или не-ref struct.
  • Не ref struct удается реализовать интерфейсы.
  • Не ref struct удается включить System.ValueType в поле или System.Object.
  • Аргумент ref struct типа не может быть аргументом типа.
  • Переменная ref struct не может быть захвачена лямбда-выражениемили локальной функцией.
  • Переменная ref struct не может использоваться в методе async . Однако переменные можно использовать ref struct в синхронных методах, например в методах, возвращающих Task или Task<TResult>.
  • Переменная ref struct не может использоваться в итераторах.

Можно определить утилизированную ref struct. Для этого убедитесь, что ref struct шаблон подходит для удаления. То есть он имеет метод экземпляра Dispose , который доступен, без параметров и имеет тип возвращаемого void значения. Вы можете использовать инструкцию using или объявление с экземпляром удаленного объекта ref struct.

Как правило, вы определяете ref struct тип, если требуется тип, который также включает элементы ref struct данных типов:

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

Чтобы объявить как ref structreadonly, объедините readonly модификаторы и ref модификаторы в объявлении типа ( readonly модификатор должен прийти перед модификатором 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; }
}

В .NET примеры ref struct : System.Span<T> и System.ReadOnlySpan<T>.

ref Поля

Начиная с C# 11, можно объявить ref поле в виде ref structследующего примера:

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

Поле ref может иметь null значение. Unsafe.IsNullRef<T>(T) Используйте метод, чтобы определить, является nullли ref поле.

Модификатор можно применить к ref полю readonly следующим образом:

  • readonly ref: можно переназначить такое поле = ref только в конструкторе или методе initдоступа. Можно назначить значение оператору = в любой точке, разрешенной модификатором доступа к полю.
  • ref readonly: в любой момент нельзя назначить значение оператору = для такого поля. Однако можно переназначить поле оператором = ref .
  • readonly ref readonly: можно переназначить такое поле только в конструкторе или методе init доступа. В любой момент нельзя назначить значение полю.

Компилятор гарантирует, что ссылка, хранящуюся в ref поле, не выходит за пределы его ссылки.

Функция ref полей обеспечивает безопасную реализацию таких типов:System.Span<T>

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

    // Omitted for brevity...
}

Тип Span<T> сохраняет ссылку, через которую он обращается к смежным элементам в памяти. Использование ссылки позволяет Span<T> экземпляру избежать копирования хранилища, на которое он ссылается.

Спецификация языка C#

Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:

Дополнительные сведения о ref полях см. в заметке о улучшении структуры низкого уровня.

См. также