Упражнение. Обнаружение ссылочных типов
- 8 мин
К ссылочным типам относятся массивы, классы и строки. Ссылочные типы обрабатываются по-разному от типов значений относительно способа хранения значений при выполнении приложения.
В этом упражнении вы узнаете, как ссылочные типы отличаются от типов значений и как использовать new
оператор для связывания переменной со значением в памяти компьютера.
Отличие ссылочных типов от типов значений
Переменная типа значения хранит значения непосредственно в области хранилища, называемой стеком. Стек — это память, выделенная для кода, который выполняется центральным процессором в настоящее время (также называется кадром стека или кадром активации). Когда выполнение кадра стека завершается, значения в стеке удаляются.
Переменная ссылочного типа хранит значения в отдельном регионе памяти, называемом кучей. Куча — это область памяти, которая используется совместно приложениями, работающими в операционной системе одновременно. Среда выполнения .NET взаимодействует с операционной системой, чтобы определить доступные адреса памяти, и запрашивает адрес, по которому можно сохранить значение. Далее среда выполнения .NET сохраняет значение и возвращает адрес памяти переменной. Когда переменная используется в коде, среда выполнения .NET обращается по хранящемуся в переменной адресу и получает сохраненное значение.
Далее вы напишете код, иллюстрирующий эти идеи более четко.
Определение переменной ссылочного типа
Удалите или используйте оператор
//
строковый комментарий, чтобы закомментировать весь код из предыдущих упражнений.Обновите код в редакторе Visual Studio Code следующим образом:
int[] data;
Предыдущий код определяет переменную, которая может содержать значение массива типов
int
.На этом этапе
data
— это просто переменная, которая может содержать ссылку на значение или его адрес в куче. Так как он не указывает на адрес памяти, он называется пустой ссылкой.Создание экземпляра массива с помощью
int
ключевогоnew
словаОбновите код в редакторе Visual Studio Code, чтобы создать и назначить новый экземпляр массива
int
, используя следующий код:int[] data; data = new int[3];
Ключевое
new
слово сообщает среде выполнения .NET, чтобы создать экземпляр массива, а затем координировать работу с операционной системой, чтобы сохранить размер массиваint
для трех значений int в памяти. Среда выполнения .NET следует этим предписаниям и возвращает адрес нового массиваint
в памяти. Наконец, адрес памяти сохраняется в переменной. Элементы массиваint
по умолчанию имеют значение0
, поскольку это значение по умолчанию для типаint
.Изменение примера кода для выполнения обеих операций в одной строке кода
Как правило, две строки кода на предыдущем шаге сокращены до одной строки кода, чтобы объявить переменную и создать новый экземпляр массива
int
. Измените код из шага 3 следующим образом.int[] data = new int[3];
Хотя нет выходных данных для наблюдения, надеюсь, это упражнение добавило ясность в том, как синтаксис C# относится к шагам процесса для работы с ссылочными типами.
Что отличается от типа данных строки C#?
Тип данных string
также является ссылочным. Возможно, вам интересно, почему new
оператор не использовался при объявлении строки. Это сделано авторами языка C# исключительно в целях удобства,
string
Так как тип данных используется так часто, можно использовать следующий формат:
string shortenedString = "Hello World!";
Console.WriteLine(shortenedString);
Однако за кулисами создается новый экземпляр System.String
, который инициализируется как "Hello World!"
Практические проблемы с использованием типов значений и ссылок
-
Тип значения (int): в этом примере
val_A
иval_B
являются целыми типами значений.
int val_A = 2;
int val_B = val_A;
val_B = 5;
Console.WriteLine("--Value Types--");
Console.WriteLine($"val_A: {val_A}");
Console.WriteLine($"val_B: {val_B}");
Должен появиться следующий результат:
--Value Types--
val_A: 2
val_B: 5
При val_B = val_A
выполнении значение val_A
копируется и сохраняется в val_B
. Таким образом, когда val_B
изменение изменяется, val_A
остается небезопасным.
-
Ссылочный тип (массив): в этом примере
ref_A
иref_B
являются ссылочными типами массивов.
int[] ref_A= new int[1];
ref_A[0] = 2;
int[] ref_B = ref_A;
ref_B[0] = 5;
Console.WriteLine("--Reference Types--");
Console.WriteLine($"ref_A[0]: {ref_A[0]}");
Console.WriteLine($"ref_B[0]: {ref_B[0]}");
Должен появиться следующий результат:
--Reference Types--
ref_A[0]: 5
ref_B[0]: 5
При ref_B = ref_A
выполнении указывает на то же расположение памяти, ref_B
что ref_A
и . Таким образом, при ref_B[0]
изменении также изменяется, ref_A[0]
так как они оба указывают на одно расположение памяти. Это ключевое различие между типами значений и ссылочными типами.
Кратко
- Типы значений имеют меньшие допустимые значения и хранятся в стеке. Ссылочные типы могут содержать большие значения, а экземпляр ссылочного типа создается с помощью оператора
new
. Переменная ссылочного типа содержат ссылку (адрес памяти) на фактическое значение, хранящееся в куче. - К ссылочным типам относятся массивы, строки и классы.