Что такое value type c
Перейти к содержимому

Что такое value type c

  • автор:

Value Type and Reference Type

In C#, these data types are categorized based on how they store their value in the memory. C# includes the following categories of data types:

  1. Value type
  2. Reference type
  3. Pointer type

Value Type

A data type is a value type if it holds a data value within its own memory space. It means the variables of these data types directly contain values.

tip

All the value types derive from System.ValueType, which in-turn, derives from System.Object.

For example, consider integer variable int i = 100;

The system stores 100 in the memory space allocated for the variable i . The following image illustrates how 100 is stored at some hypothetical location in the memory (0x239110) for ‘i’:

The following data types are all of value type:

Passing Value Type Variables

When you pass a value-type variable from one method to another, the system creates a separate copy of a variable in another method. If value got changed in the one method, it wouldn’t affect the variable in another method.

Example: Passing Value Type Variables

static void ChangeValue(int x) < x = 200; Console.WriteLine(x); > static void Main(string[] args) < int i = 100; Console.WriteLine(i); ChangeValue(i); Console.WriteLine(i); > 

100
200
100

In the above example, variable i in the Main() method remains unchanged even after we pass it to the ChangeValue() method and change it’s value there.

Reference Type

Unlike value types, a reference type doesn’t store its value directly. Instead, it stores the address where the value is being stored. In other words, a reference type contains a pointer to another memory location that holds the data.

For example, consider the following string variable:

string s = «Hello World!!»;

The following image shows how the system allocates the memory for the above string variable.

As you can see in the above image, the system selects a random location in memory (0x803200) for the variable s . The value of a variable s is 0x600000 , which is the memory address of the actual data value. Thus, reference type stores the address of the location where the actual value is stored instead of the value itself.

The followings are reference type data types:

  • String
  • Arrays (even if their elements are value types)
  • Class
  • Delegate

Passing Reference Type Variables

When you pass a reference type variable from one method to another, it doesn’t create a new copy; instead, it passes the variable’s address. So, If we change the value of a variable in a method, it will also be reflected in the calling method.

Example: Passing Reference Type Variable

static void ChangeReferenceType(Student std2) < std2.StudentName = "Steve"; > static void Main(string[] args) < Student std1 = new Student(); std1.StudentName = "Bill"; ChangeReferenceType(std1); Console.WriteLine(std1.StudentName); > 

In the above example, we pass the Student object std1 to the ChangeReferenceType() method. Here, it actually pass the memory address of std1 . Thus, when the ChangeReferenceType() method changes StudentName , it is actually changing StudentName of std1 object, because std1 and std2 are both pointing to the same address in memory.

String is a reference type, but it is immutable. It means once we assigned a value, it cannot be changed. If we change a string value, then the compiler creates a new string object in the memory and point a variable to the new memory location. So, passing a string value to a function will create a new variable in the memory, and any change in the value in the function will not be reflected in the original value, as shown below.

Example: Passing String

static void ChangeReferenceType(string name) < name = "Steve"; > static void Main(string[] args) < string name = "Bill"; ChangeReferenceType(name); Console.WriteLine(name); > 

Null

The default value of a reference type variable is null when they are not initialized. Null means not refering to any object.

A value type variable cannot be null because it holds value, not a memory address. C# 2.0 introduced nullable types, using which you can assign null to a value type variable or declare a value type variable without assigning a value to it.

Related Articles

  • How to get the sizeof a datatype in C#?
  • Difference between String and StringBuilder in C#
  • Static vs Singleton in C#
  • Difference between == and Equals() Method in C#
  • Asynchronous programming with async, await, Task in C#
  • How to loop through an enum in C#?
  • Generate Random Numbers in C#
  • Difference between Two Dates in C#
  • Convert int to enum in C#
  • BigInteger Data Type in C#
  • Convert String to Enum in C#
  • Convert an Object to JSON in C#
  • Convert JSON String to Object in C#
  • DateTime Formats in C#
  • How to convert date object to string in C#?
  • Compare strings in C#
  • How to count elements in C# array?
  • Difference between String and string in C#.
  • How to get a comma separated string from an array in C#?
  • Boxing and Unboxing in C#
  • How to convert string to int in C#?
  • More C# articles

Platform::ValueType — класс

Класс ValueType используется для создания типов значений. Класс ValueType является производным от класса Object, который содержит базовые элементы. Однако компилятор отсоединяет эти базовые элементы от типов значений, которые являются производными от класса ValueType. При упаковке типа значения компилятор снова присоединяет эти базовые элементы.

Требования

Минимальный поддерживаемый клиент: Windows 8

Минимальный поддерживаемый сервер: Windows Server 2012

Пространство имен: Platform

Метаданные: platform.winmd

Метод ValueType::ToString

Возвращает строковое представление объекта.

Синтаксис

Platform::String ToString(); 

Возвращаемое значение

Платформа::String, представляющая значение.

Что такое value type c

Ранее мы рассматривали следующие элементарные типы данных: int, byte, double, string, object и др. Также есть сложные типы: структуры, перечисления, классы. Все эти типы данных можно разделить на типы значений, еще называемые значимыми типами, (value types) и ссылочные типы (reference types). Важно понимать между ними различия.

  • Целочисленные типы ( byte, sbyte, short, ushort, int, uint, long, ulong )
  • Типы с плавающей запятой ( float, double )
  • Тип decimal
  • Тип bool
  • Тип char
  • Перечисления enum
  • Структуры ( struct )
  • Тип object
  • Тип string
  • Классы ( class )
  • Интерфейсы ( interface )
  • Делегаты ( delegate )

В чем же между ними различия? Для этого надо понять организацию памяти в .NET. Здесь память делится на два типа: стек и куча (heap). Параметры и переменные метода, которые представляют типы значений, размещают свое значение в стеке. Стек представляет собой структуру данных, которая растет снизу вверх: каждый новый добавляемый элемент помещается поверх предыдущего. Время жизни переменных таких типов ограничено их контекстом. Физически стек — это некоторая область памяти в адресном пространстве.

Когда программа только запускается на выполнение, в конце блока памяти, зарезервированного для стека устанавливается указатель стека. При помещении данных в стек указатель переустанавливается таким образом, что снова указывает на новое свободное место. При вызове каждого отдельного метода в стеке будет выделяться область памяти или фрейм стека, где будут храниться значения его параметров и переменных.

class Program < static void Main(string[] args) < Calculate(5); >static void Calculate(int t) < int x = 6; int y = 7; int z = y + t; >>

При запуске такой программы в стеке будут определяться два фрейма — для метода Main (так как он вызывается при запуске программы) и для метода Calculate:

Структура стека в языке программирования C#

При вызове этого метода Calculate в его фрейм в стеке будут помещаться значения t, x, y и z. Они определяются в контексте данного метода. Когда метод отработает, область памяти, которая выделялась под стек, впоследствии может быть использована другими методами.

Причем если параметр или переменная метода представляет тип значений, то в стеке будет храниться непосредсвенное значение этого параметра или переменной. Например, в данном случае переменные и параметр метода Calculate представляют значимый тип — тип int, поэтому в стеке будут храниться их числовые значения.

Ссылочные типы хранятся в куче или хипе, которую можно представить как неупорядоченный набор разнородных объектов. Физически это остальная часть памяти, которая доступна процессу.

При создании объекта ссылочного типа в стеке помещается ссылка на адрес в куче (хипе). Когда объект ссылочного типа перестает использоваться, в дело вступает автоматический сборщик мусора: он видит, что на объект в хипе нету больше ссылок, условно удаляет этот объект и очищает память — фактически помечает, что данный сегмент памяти может быть использован для хранения других данных.

Так, в частности, если мы изменим метод Calculate следующим образом:

static void Calculate(int t)

То теперь значение переменной x будет храниться в куче, так как она представляет ссылочный тип object, а в стеке будет храниться ссылка на объект в куче.

Ссылочные типы в куче в языке программирования C#

Составные типы

Теперь рассмотим ситуацию, когда тип значений и ссылочный тип представляют составные типы — структуру и класс:

State state1 = new State(); // State — структура, ее данные размещены в стеке Country country1 = new Country(); // Country — класс, в стек помещается ссылка на адрес в хипе // а в хипе располагаются все данные объекта country1 struct State < public int x; public int y; >class Country

Здесь в методе Main в стеке выделяется память для объекта state1. Далее в стеке создается ссылка для объекта country1 ( Country country1 ), а с помощью вызова конструктора с ключевым словом new выделяется место в хипе ( new Country() ). Ссылка в стеке для объекта country1 будет представлять адрес на место в хипе, по которому размещен данный объект..

Ссылычные типы и типы значений в C#

Таким образом, в стеке окажутся все поля структуры state1 и ссылка на объект country1 в хипе.

Но, допустим, в структуре State также определена переменная ссылочного типа Country. Где она будет хранить свое значение, если она определена в типе значений?

State state1 = new State(); Country country1 = new Country(); struct State < public int x; public int y; public Country country; public State() < x = 0; y = 0; country = new Country(); >> class Country

Значение переменной state1.country также будет храниться в куче, так как эта переменная представляет ссылочный тип:

Стек и куча в языке программирования C#

Копирование значений

Тип данных надо учитывать при копировании значений. При присвоении данных объекту значимого типа он получает копию данных. При присвоении данных объекту ссылочного типа он получает не копию объекта, а ссылку на этот объект в хипе. Например:

State state1 = new State(); // Структура State State state2 = new State(); state2.x = 1; state2.y = 2; state1 = state2; state2.x = 5; // state1.x=1 по-прежнему Console.WriteLine(state1.x); // 1 Console.WriteLine(state2.x); // 5 Country country1 = new Country(); // Класс Country Country country2 = new Country(); country2.x = 1; country2.y = 4; country1 = country2; country2.x = 7; // теперь и country1.x = 7, так как обе ссылки и country1 и country2 // указывают на один объект в хипе Console.WriteLine(country1.x); // 7 Console.WriteLine(country2.x); // 7

Так как state1 — структура, то при присвоении state1 = state2 она получает копию структуры state2. А объект класса country1 при присвоении country1 = country2; получает ссылку на тот же объект, на который указывает country2. Поэтому с изменением country2, так же будет меняться и country1.

Ссылочные типы внутри типов значений

Теперь рассмотрим более изощренный пример, когда внутри структуры у нас может быть переменная ссылочного типа, например, какого-нибудь класса:

State state1 = new State(); State state2 = new State(); state2.country.x = 5; state1 = state2; state2.country.x = 8; // теперь и state1.country.x=8, так как state1.country и state2.country // указывают на один объект в хипе Console.WriteLine(state1.country.x); // 8 Console.WriteLine(state2.country.x); // 8 struct State < public int x; public int y; public Country country; public State() < x = 0; y = 0; country = new Country(); // выделение памяти для объекта Country >> class Country

Переменные ссылочных типов в структурах также сохраняют в стеке ссылку на объект в хипе. И при присвоении двух структур state1 = state2; структура state1 также получит ссылку на объект country в хипе. Поэтому изменение state2.country повлечет за собой также изменение state1.country.

Объекты классов как параметры методов

Организацию объектов в памяти следует учитывать при передаче параметров по значению и по ссылке. Если параметры методов представляют объекты классов, то использование параметров имеет некоторые особенности. Например, создадим метод, который в качестве параметра принимает объект Person:

Person p = new Person < name = "Tom", age = 23 >; ChangePerson(p); Console.WriteLine(p.name); // Alice Console.WriteLine(p.age); // 23 void ChangePerson(Person person) < // сработает person.name = "Alice"; // сработает только в рамках данного метода person = new Person < name = "Bill", age = 45 >; Console.WriteLine(person.name); // Bill > class Person

При передаче объекта класса по значению в метод передается копия ссылки на объект. Эта копия указывает на тот же объект, что и исходная ссылка, потому мы можем изменить отдельные поля и свойства объекта, но не можем изменить сам объект. Поэтому в примере выше сработает только строка person.name = «Alice» .

А другая строка person = new Person < name = "Bill", age = 45 >создаст новый объект в памяти, и person теперь будет указывать на новый объект в памяти. Даже если после этого мы его изменим, то это никак не повлияет на ссылку p в методе Main, поскольку ссылка p все еще указывает на старый объект в памяти.

Но при передаче параметра по ссылке (с помощью ключевого слова ref ) в метод в качестве аргумента передается сама ссылка на объект в памяти. Поэтому можно изменить как поля и свойства объекта, так и сам объект:

Person p = new Person < name = "Tom", age = 23 >; ChangePerson(ref p); Console.WriteLine(p.name); // Bill Console.WriteLine(p.age); // 45 void ChangePerson(ref Person person) < // сработает person.name = "Alice"; // сработает person = new Person < name = "Bill", age = 45 >; > class Person

Операция new создаст новый объект в памяти, и теперь ссылка person (она же ссылка p из метода Main) будет указывать уже на новый объект в памяти.

Value Type и Reference Type или чем стек отличается от кучи?

Итак, разберемся что такое Value Type и Reference Type и чем стек отличается от кучи.
В Swift есть две категории типов:

  • Value Type (Тип значения) — каждый экземпляр хранит уникальную копию своих данных. То есть происходит создание нового экземпляра (копии) при присвоении значения переменной/константе или при передаче экземпляра в функцию.
  • Reference Type (Ссылочный тип) — каждый экземпляр использует одну копию данных. То есть сохраняется/возвращается ссылка на тот же экземпляр при присвоении значения переменной/константе или при передаче экземпляра в функцию.

Давайте разделим типы в Swift на две категории:

Тип значения Ссылочный тип
Int Функции
Double Замыкания
String Классы
Array
Dictionary
Set
Struct
Enum
Tuple
  • Экземпляры ссылочного типа (Reference Type), например, функции или классы хранятся в управляемой динамической памяти — куче (heap).
  • Экземпляры типа значения (Value Type), такие, как структура или массив, находятся в области памяти, называемой стеком (stack).

Существует одно важное замечание — если экземпляр типа значения является частью экземпляра ссылочного типа, то значение сохраняется в куче вместе с экземпляром ссылочного типа. Например, структура сама по себе хранится в стеке, но если эта структура расположена в классе, то так как класс хранится в куче, то и структура будет сохранена в куче.

Стек используется для распределения статической памяти, а куча — для распределения динамической памяти, которая хранятся в оперативной памяти компьютера.

  • Difference between value type and a reference type in iOS swift?
  • Value and Reference Types
  • Управление памятью в Swift

Выразить благодарность или найти уникальный материал вы можете в boosty.

Подписывайтесь на мой Telegram-канал iOS Interview Channel, чтобы не пропустить новый материал.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *