Ref class c что это
ref class и ref struct (C++/CLI и C++/CX)
Расширения ref class или ref struct объявляют класс или структуру со временем жизни объекта, которое администрируется автоматически. Когда объект становится недоступным или выходит за пределы области, память освобождается.
Все среды выполнения
Синтаксис
Параметры
class_access
(Необязательно) Доступность класса или структуры вне сборки. Возможные значения: public и private ( private используется по умолчанию). Вложенные классы и структуры не могут иметь описатель class_access.
name
Имя класса или структуры.
Модификатор
(Необязательно) Допустимые модификаторы — abstract и sealed.
inherit_access
(Необязательно) Доступность base_type. Единственным разрешенным доступом является public ( public является значением по умолчанию).
base_type
(Необязательно) Базовый тип. Однако тип значения не может действовать как базовый тип.
Дополнительные сведения см. в описаниях этого параметра для конкретного языка в разделах «Среда выполнения Windows» и «Среда CLR».
Remarks
Дополнительные сведения о классах и структурах см. в разделе
Среда выполнения Windows
Remarks
Параметры
base_type
(Необязательно) Базовый тип. ref class или ref struct могут наследовать от произвольного числа (включая 0) интерфейсов и от ноля или одного типа ref. value class или value struct могут наследовать только от произвольного числа (включая 0) интерфейсов.
Если объект объявлен с помощью ключевых слов ref class или ref struct, он доступен дескриптору объекта, т. е. указателю счетчика ссылок на объект. Если объявленная переменная выходит за пределы области, компилятор автоматически удаляет базовый объект. Когда объект используется в качестве параметра в вызове или хранится в переменной, фактически передается или хранится только его дескриптор.
При объявлении объекта с помощью ключевых слов value class или value struct время жизни объявленного объекта не контролируется. Этот объект аналогичен любому другому стандартному классу или структуре C++.
Требования
Параметр компилятора: /ZW
Среда CLR
Remarks
В следующей таблице перечислены отличия от синтаксиса, показанного в разделе Все среды выполнения, которые характерны для C++/CLI.
Параметры
base_type
(Необязательно) Базовый тип. ref class или ref struct может наследовать от произвольного числа (включая 0) управляемых интерфейсов и от ноля или одного типа ref. value class или value struct может наследовать только от произвольного числа (включая 0) управляемых интерфейсов.
Ключевые слова ref class и ref struct сообщают компилятору, что класс или структура должны выделяться в куче. Когда объект используется в качестве параметра в вызове или хранится в переменной, фактически передается или хранится только ссылка на него.
Ключевые слова value class и value struct сообщают компилятору, что значение выделенного класса или структуры передается функциям или сохраняется в элементах.
ref (Справочник по C#)
Ключевое слово ref указывает, что значение передается по ссылке. Оно используется в четырех разных контекстах:
Передача аргументов по ссылке
При использовании в списке параметров метода ключевое слово ref указывает на то, что аргумент передается по ссылке, а не по значению. Ключевое слово ref позволяет превратить этот формальный параметр в псевдоним для аргумента, который должен представлять собой переменную. Другими словами, любая операция в параметре осуществляется с аргументом.
Для примера предположим, что вызывающая сторона передает выражение локальной переменной или выражение доступа к элементу массива. Тогда вызываемый метод может заменить объект, на который ссылается параметр ref. В этом случае или элемент массива или локальная переменная вызывающей стороны будет ссылаться на новый объект, когда метод возвращает значение.
Не путайте понятие передачи по ссылке с понятием ссылочных типов. Эти два понятия не совпадают. Параметр метода может быть изменен с помощью ref независимо от того, принадлежит ли он к типу значения или ссылочному типу. При передаче по ссылке упаковка-преобразование типа значения не производится.
Методы расширения также имеют ряд ограничений при использовании этих ключевых слов:
Передача аргументов по ссылке. Пример
Дополнительные сведения о передаче ссылочных типов по значению и по ссылке см. в разделе Передача параметров ссылочного типа.
Возвращаемые ссылочные значения
Возвращаемые ссылочные значения — это значения, которые метод возвращает вызывающему объекту по ссылке. Это значит, что вызывающий объект может изменять значение, возвращаемое методом, и это изменение будет отражаться в состоянии объекта в вызывающем методе.
Возвращаемое ссылочное значение определяется с помощью ключевого слова ref :
Чтобы вызывающий объект имел возможность изменять состояние объекта, возвращаемое ссылочное значение должно храниться в переменной, которая явно определена как ссылочная локальная переменная.
Ниже приведен более полный пример возвращаемого ссылочного значения, в котором показаны сигнатура и тело метода.
Ссылочные локальные переменные
Чтобы определить локальное ссылочное значение, ключевое слово ref следует указать в двух местах:
Например, следующая инструкция определяет значение ссылочной локальной переменной, которое возвращается методом GetEstimatedValue :
Вы можете таким же образом обратиться к значению по ссылке. В некоторых случаях обращение к значению по ссылке повышает производительность, поскольку позволяет избежать потенциально затратной операции копирования. Например, следующая инструкция позволяет определить локальную ссылочную переменную, которая используется для создания ссылки на значение.
В обоих примерах ключевое слово ref необходимо использовать в обоих местах. В противном случае возникает ошибка компилятора CS8172, «Невозможно инициализировать значением переменную по ссылке».
Начиная с версии C# 7.3, переменная итерации в операторе foreach может являться локальной ссылочной переменной или локальной ссылочной переменной только для чтения. Дополнительные сведения см. в статье, посвященной инструкции foreach.
Также, начиная с версии C# 7.3, вы можете переназначать ссылочную локальную переменную или ссылочную локальную переменную только для чтения с помощью ссылочного оператора присваивания.
Ссылочные локальные переменные только для чтения
Пример использования возвращаемых ссылочных значений и ссылочных локальных переменных
Спецификация языка C#
Дополнительные сведения см. в спецификации языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.
BestProg
Содержание
Поиск на других ресурсах:
Модификатор параметра ref используется в описании формального параметра метода. Модификатор параметра ref указывается перед типом формального параметра, как показано ниже:
Общая форма метода в классе, который получает формальный параметр ref следующая:
При вызове такого метода из другого кода, перед параметром также ставится модификатор ref :
где argument – аргумент, который передается в метод. Этого требует синтаксис C#.
⇑
2. Примеры методов, которые используют модификатор параметра ref
Вызов метода Mult5() из другого программного кода
Вызов метода из другого класса может быть таким как описан низшее
Следует заметить, что при вызове метода Calc() обязательно указываются модификаторы ref :
⇑
Модификатор параметра out используется, если необходимо выполнение двух условий:
Модификатор out для параметра с именем param типа type указывается в начале его объявления
Общая форма метода, который получает один параметр с модификатором out имеет вид
⇑
4. Примеры методов, которые используют модификатор параметра out
Пример 1. Разработать метод, который возвращает число Авогадро. Число Авогадро задается параметром метода.
Текст метода:
Вызов метода из другого программного кода
Пример 3. Разработать метод, который возвращает название цифры в строке.
Использование метода TextNumber() класса Number
⇑
Между модификаторами ref и out есть три взаимосвязанных отличия:
⇑
Результат выполнения программы
⇑
Классы и структуры ссылки (C++/CX)
C++/CX поддерживает определяемые пользователем ссылочные классы и Ссылочные структуры, а также пользовательские классы значений и структуры значений. эти структуры данных являются основными контейнерами, по которым C++/cx поддерживает систему типов среда выполнения Windows. их содержимое передается в метаданные в соответствии с определенными правилами, и это позволяет передавать их между компонентами среда выполнения Windows и универсальная платформа Windows приложениями, написанными на C++ или на других языках.
Класс ссылки и структура ссылки имеют следующие основные особенности:
они могут реализовывать один или несколько классов интерфейсов или структур интерфейсов;
они могут наследовать одному базовому классу, а на сами базовые классы налагаются дополнительные ограничения. Наследование в иерархиях открытых классов ссылок имеет больше ограничений, чем наследование закрытых классов ссылок;
они не могут объявляться как универсальные. Если они имеют закрытый доступ, они могут быть шаблонами;
Их время жизни управляется автоматическим подсчетом ссылок.
Объявление
Реализация
Использование
Также можно также объявить локальную переменную класса ссылки с помощью семантики стека. Поведение такого объекта аналогично поведению стековой переменной, несмотря на то что память все же выделяется динамически. Важное отличие заключается в том, что нельзя присвоить отслеживаемую ссылку (%) переменной, объявленной с использованием семантики стека: таким образом гарантируется, что счетчик ссылок уменьшается до нуля, когда выполняется выход из функции. В этом примере показаны базовый класс ссылки Uri и функция, в которой он используется с семантикой стека:
Управление памятью
Класс ссылки выделяется в динамической памяти с помощью ref new ключевого слова.
По определению класс ссылки имеет семантику ссылки. Когда вы присваиваете значение переменной класса ссылки, копируется не сам объект, а его дескриптор. В следующем примере после операции присваивания оба объекта myClass и myClass2 указывают на одно и то же расположение в памяти.
Когда создается экземпляр класса ссылки C++/CX, его память перед вызовом конструктора инициализируется нулями, поэтому такая инициализация для отдельных членов, включая свойства, не требуется. Если класс C++/CX является производным от класса библиотеки C++ для среды выполнения Windows (WRL), инициализация нулями осуществляется только для области производного класса C++/CX.
Элементы
Структура ref аналогична ссылочному классу, за исключением того, что ее члены по умолчанию имеют public доступ.
public ссылочный класс или структура ссылки создаются в метаданных, но их можно использовать из других универсальная платформа Windows приложений и среда выполнения Windows компонентов, которые должны иметь по крайней мере один открытый или защищенный конструктор. Открытый класс ссылки, имеющий открытый конструктор, также должен быть объявлен как sealed для предотвращения дальнейшего наследования через двоичный интерфейс приложения (ABI).
При определении открытого класса или структуры ссылок компилятор применяет необходимые атрибуты к классу и сохраняет эти сведения в файле WinMD приложения. однако при определении открытого незапечатанного класса ссылки вручную примените Windows::Foundation::Metadata::WebHostHidden атрибут, чтобы класс не был видимым для универсальная платформа Windows приложений, написанных на JavaScript.
Открытые классы ссылки, имеющие параметры-типы, не допускаются. Определяемые пользователем универсальные классы ссылок не допускаются. Класс ссылки с атрибутами private, internal или protected private может быть шаблоном.
Деструкторы
В C++/CX вызов метода delete в открытом деструкторе вызывает деструктор независимо от счетчика ссылок объекта. Это позволяет определить деструктор, который будет выполнять пользовательскую очистку ресурсов, не относящихся к RAII, детерминированным образом. Однако даже в этом случае сам объект не удаляется из памяти. Память для объекта освобождается, только когда число ссылок достигает нуля.
Если деструктор класса не является общим, он вызывается только в случае, когда число ссылок достигает нуля. При вызове delete для объекта, имеющего закрытый деструктор, компилятор выдает предупреждение C4493, что говорит о том, что выражение delete не действует, так как деструктор не имеет модификатора public.
Деструкторы классов ссылок можно объявлять только следующим образом:
открытый и виртуальный (допускается только для запечатанных и незапечатанных типов);
защищенный закрытый и невиртуальный (допускается только для незапечатанных типов);
закрытый и невиртуальный (допускается только для запечатанных типов).
Никакие другие сочетания режимов доступа, виртуальности и запечатанности не допускаются. Если деструктор явно не объявлен, компилятор создает открытый виртуальный деструктор, если у базового класса типа или любого из его членов имеется открытый деструктор. В противном случае компилятор создает защищенный закрытый невиртуальный деструктор для незапечатанных типов и закрытый невиртуальный деструктор для запечатанных типов.
При попытке обращения к членам класса, для которого уже запускался деструктор, поведение будет неопределенным; это наиболее вероятная причина сбоя программы. При вызове delete t для типа, у которого нет открытого деструктора, ничего не происходит. Вызов delete this для типа или базового класса, который имеет известный private деструктор или protected private из его иерархии типов, не оказывает никакого влияния.
Наследование
Platform::Object является универсальным базовым классом для всех классов ссылок. Все классы ссылок неявно преобразуются в Platform::Object и могут переопределять Object::ToString. однако модель наследования среда выполнения Windows не предназначена как общая модель наследования. в C++/CX это означает, что определяемый пользователем открытый класс ссылки не может служить базовым классом.
Закрытый базовый класс ссылки не требуется для наследования от существующего незапечатанного класса. Если требуется, чтобы иерархия объектов моделировала собственную структуру программы или обеспечивала повторное использование кода, используйте закрытые или внутренние классы ссылок, а лучше стандартные классы C++. Доступ к функциональности закрытой иерархии объектов можно реализовать с помощью оболочки открытого запечатанного класса ссылки.
Класс ссылки, имеющий открытый или защищенный конструктор в C++/CX, должен быть объявлен как Sealed. это ограничение означает, что для классов, написанных на других языках, таких как C# или Visual Basic, не существует способа наследования от типов, объявляемых в среда выполнения Windows компоненте, написанном на C++/CX.
Ниже приведены основные правила наследования в C++/CX.
классы ссылок могут напрямую наследовать не более чем от одного базового класса, но могут реализовывать любое количество интерфейсов;
если у класса имеется открытый конструктор, он должен объявляться как запечатанный, чтобы запретить его дальнейшее наследование;
для классов ссылок поддерживается только открытое наследование.
В следующем примере показано, как предоставлять доступ к открытому классу ссылки, производному от других классов ссылки в иерархии наследования.
Возвращаемые ссылочные значения и ссылочные локальные переменные
Начиная с версии 7.0 язык C# поддерживает значения, возвращаемые по ссылке (возвращаемые ссылочные значения). Возвращаемое ссылочное значение позволяет методу вернуть вызывающей стороне ссылку на переменную, а не фиксированное значение. После этого вызывающий может самостоятельно решить, как обрабатывать полученную переменную: по значению или по ссылке. Вызывающий может создать новую переменную и присвоить ей ссылку на полученное значение (локальная ссылочная переменная).
Что представляет собой возвращаемое ссылочное значение?
Большинство разработчиков прекрасно знакомы с передачей аргумента в вызываемый метод по ссылке. Список аргументов вызываемого метода включает переменную, переданную по ссылке. Вызывающий может отследить любые изменения этого значения в вызываемом методе. Возвращаемое ссылочное значение означает, что метод возвращает ссылку на некоторую переменную (или ее псевдоним). В область действия переменной должен входить этот метод. Время существования переменной должно продолжаться после того, как метод возвращает управление. Все изменения, которые вызывающий производит с возвращаемым значением метода, применяются к возвращенной переменной.
Есть несколько ограничений для выражений, которые можно использовать в качестве возвращаемых ссылочных значений метода. К ним относятся указанные ниже ограничения.
Время существования возвращаемого значения должно превышать период выполнения метода. Другими словами, нельзя возвращать ссылку на локальную переменную вызываемого метода. Это может быть экземпляр статического поля или класса, а также переданный в метод аргумент. При попытке возвратить локальную переменную возникает ошибка компилятора CS8168 «Невозможно вернуть по ссылке локальный «obj», так как это не локальная переменная ref».
Метод с возвращаемым ссылочным значением может возвращать псевдоним для переменной с текущим значением NULL (которой не присвоены экземпляры) или тип, допускающий значение NULL.
Кроме того, возвращаемые ссылочные значения недопустимы в асинхронных методах. Асинхронный метод может вернуть управление до того, как будет завершено его выполнение и станет известно его возвращаемое значение.
Определение возвращаемого ссылочного значения
Метод, который возвращает возвращаемое значение ссылки, должен удовлетворять следующим двум условиям:
В следующем примере показан метод, который удовлетворяет указанным условиям и возвращает ссылку на объект Person с именем p :
Использование возвращаемого ссылочного значения
Возвращаемое ссылочное значение является псевдонимом для другой переменной в области вызываемого метода. Любое применение возвращаемого ссылочного значения можно рассматривать как применение псевдонима соответствующей переменной.
Ссылочные локальные переменные
Предположим, что для метода GetContactInformation объявлено возвращаемое ссылочное значение:
При назначении по значению считывается значение переменной и присваивается это значение новой переменной:
Ключевое слово ref используется перед объявлением локальной переменной и до вызова метода.
Вы можете таким же образом обратиться к значению по ссылке. В некоторых случаях обращение к значению по ссылке повышает производительность, поскольку позволяет избежать потенциально затратной операции копирования. Например, в следующей инструкции показано, как можно определить локальное ссылочное значение, используемое для ссылки на значение.
Ключевое слово ref используется перед объявлением локальной переменной и перед значением во втором примере. Если не указать ключевые слова ref одновременно в объявлении и присвоении переменной в обоих примерах, возникает ошибка компилятора CS8172 «Невозможно инициализировать значением переменную по ссылке».
До версии C# 7.3 ссылочные локальные переменные нельзя было переназначить после инициализации так, чтобы они ссылались на другое хранилище. Это ограничение было снято. В следующем примере демонстрируется переназначение:
Ссылочные локальные переменные по-прежнему необходимо инициализировать во время объявления.
Пример использования возвращаемых ссылочных значений и ссылочных локальных переменных
Без использования возвращаемых ссылочных значений такая операция выполняется путем возврата индекса элемента массива вместе с его значением. После этого вызывающий объект использует индекс для изменения значения в отдельном вызове метода. Тем не менее вызывающий объект также может изменить индекс для доступа к другим значениям массива и их изменения.
В следующем примере показано, как можно изменить метод FindNumber в версии C# 7.3 или более поздней, чтобы использовать переназначение ссылочной локальной переменной:
Эта вторая версия работает эффективнее с более длинными последовательностями в сценариях, в которых искомое число находится ближе к концу массива, так как итерация массива выполняется от конца к началу, что приводит к проверке меньшего числа элементов.