Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Модификатор можно использовать ref в объявлении типа структуры. Экземпляры ref struct типа выделяются в стеке и не могут экранироваться в управляемую кучу. Чтобы убедиться, что компилятор ограничивает использование ref struct типов следующим образом:
- Не
ref structможет быть типом элемента массива. - Не
ref structможет быть объявленным типом поля класса или не-ref struct. - Не
ref structудается включить System.ValueType в поле или System.Object. - Переменная
ref structне может быть записана в лямбда-выраженииили локальной функции. - До C# 13
ref structпеременные нельзя использовать в методеasync. Начиная с C# 13 переменнаяref structне может использоваться в том же блоке, чтоawaitи выражение в методеasync. Однако переменные можно использоватьref structв синхронных методах, например в методах, возвращающих Task или Task<TResult>. - До C# 13
ref structпеременная не может использоваться в итераторах. Начиная с C# 13,ref structтипы иrefлокальные типы можно использовать в итераторах, если они не содержатся в сегментах кода с инструкциейyield return. - До C# 13
ref structне удается реализовать интерфейсы. Начиная с C# 13 структураrefможет реализовывать интерфейсы, но должна соответствовать правилам безопасности ссылок . Например, тип нельзя преобразовать в тип интерфейса,ref structтак как для этого требуется преобразование бокса. - До C# 13
ref structне может быть аргументом типа. Начиная с C# 13, аргумент типа может быть аргументом типа,ref structесли параметр типа указываетallows ref structв предложении.where
Как правило, вы определяете 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 Поля
Вы можете объявить 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) Используйте метод, чтобы определить, является refли null поле.
Модификатор можно применить к readonly полю ref следующим образом:
-
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> экземпляру избежать копирования хранилища, на которое он ссылается.
Шаблон, допускающий удаление
Можно определить утилизированную ref struct. Для этого убедитесь, что ref struct шаблон подходит для удаления. То есть он имеет метод экземпляра Dispose , который доступен, без параметров и имеет тип возвращаемого void значения. Вы можете использовать инструкцию using или объявление с экземпляром удаленного объекта ref struct.
Начиная с C# 13, можно также реализовать IDisposableref struct типы. Однако разрешение перегрузки предпочитает уменяемый шаблон для метода интерфейса. Компилятор разрешает IDisposable.Dispose метод только в том случае, если подходящий Dispose метод не найден.
Ограничения для ref struct типов, реализующих интерфейс
Эти ограничения гарантируют, что ref struct тип, реализующий интерфейс, подчиняется необходимым правилам безопасности ссылок.
- Невозможно
ref structпреобразовать его в экземпляр интерфейса, который он реализует. Это ограничение включает неявное преобразование при использованииref structтипа в качестве аргумента, если параметр является типом интерфейса. Преобразование приводит к преобразованию бокса, которое нарушает безопасность ссылок.ref structможет объявлять методы как явные объявления интерфейса. Однако к этим методам можно обращаться только из универсальных методов, где параметр типа соответствует типамallows ref struct. -
ref struct, реализующий интерфейс , должен реализовать все экземплярные члены интерфейса.ref structдолжен реализовывать членов экземпляра, даже если интерфейс включает реализацию по умолчанию.
Компилятор применяет эти ограничения. При написании ref struct типов, реализующих интерфейсы, каждое новое обновление может включать новые члены интерфейса по умолчанию. Пока вы не предоставите реализацию для любых новых методов экземпляра, приложение не компилируется. Нельзя предоставить конкретную реализацию для метода интерфейса static с реализацией по умолчанию.
Внимание
Реализация ref struct интерфейса включает потенциал для последующих исходных и двоичных изменений. Разрыв возникает, если ref struct интерфейс, определенный в другой сборке, и эта сборка предоставляет обновление, которое добавляет элементы по умолчанию в этот интерфейс.
Нарушение совместимости исходного кода происходит при повторной компиляции ref struct: он должен реализовать новый член, несмотря на то, что существует реализация по умолчанию.
Двоичный разрыв происходит при обновлении внешней сборки без повторной компиляции ref struct типа , а обновленный код вызывает реализацию нового метода по умолчанию. Среда выполнения создает исключение при доступе к члену по умолчанию.
Спецификация языка C#
Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:
Дополнительные сведения о ref полях см. в заметке о улучшении структуры низкого уровня.