В CTS (и, следовательно, в С#) есть две группы типов — значащие и ссылочные. К значащим относятся большинство примитивных типов (int, float и т. д.), а также перечисления и структуры.
Главным отличием значащих типов от ссылочных является способ их представления в памяти компьютера. Для первых память выделяется в программном стеке, а имя соответствующей переменной прямо связывается с этой памятью. Иными словами, если инициализирована переменная значащего типа, имя этой переменной адресует участок стека, в котором она расположена. Если создается другая переменная того же значащего типа, ей выделяется другая область стека того же размера. Для ссылочных типов память выделяется в управляемой системной куче, а значением переменной этого типа является адрес участка кучи, в которой расположена переменная. Если создается вторая переменная того же ссылочного типа, она получает ссылку на тот же участок кучи, что и первая. Таким образом, переменные одного и того же значащего типа независимы друг от друга, а переменные одинакового ссылочного типа — зависимы.
Это продемонстрирует программа, представленная в листинге 5.1 (файл Ch05\ValRefTypes\Program.cs).
Листинг 5.1. Значащие и ссылочные типы
using System;
// Определяем структуру с двумя целочисленными полями:
struct Foo
{
public int x, y;
}
class ValRefClass
{
static void Main()
{
// Создаем две переменные класса Foo
Foo f1 = new Foo();
Foo f2 = new Foo();
f1.x = 100;
f1.y = 200;
// Присваиваем переменной f1 значение переменной f2:
f2 = f1;
// Выводим значения переменных:
Console.WriteLine("f1.x = {0}", f1.x);
Console.WriteLine("f1.y = {0}", f1.y);
Console.WriteLine("f2.x = {0}", f2.x);
Console.WriteLine("f2.y = {0}", f2.y);
// Изменяем f1:
f1.x = 300;
// Выводим поле х обеих переменных:
Console.WriteLine("После изменения f1.x:");
Console.WriteLine("f1.x = {0}", f1.x);
Console.WriteLine("f2.x = {0}", f2.x);
Console.ReadLine();
}
}
Изменим программу: вместо значащего типа struct используем ссылочный тип class:
class Foo
{
public int x, y;
}
Все значащие типы унаследованы от класса System.ValueType, в то время как ссылочные типы могут быть наследниками любого класса, кроме System.ValueType. Поскольку экземпляры значащих типов располагаются в стеке, а ссылочных — в куче, время жизни первых заканчивается при выходе из области видимости программы (из метода, в котором объявлены соответствующие переменные). Время жизни ссылочных типов определяется алгоритмом сборки мусора.
Класс System.ValueType занимает особое место в иерархии классов CTS. С одной стороны, он является прямым наследником базового класса System.Object, с другой объявляется с модификатором abstract, что исключает возможность использования объектов этого класса. Его назначение — передать своим наследникам некоторую функциональность всех значащих типов, в том числе возможность их преобразования в ссылочный тип и обратно (см. следующий раздел). Другой важной особенностью класса является то обстоятельство, что все его многочисленные потомки (их более 100) являются не классами, а структурами. Структуры в CTS (и в С#) считаются особой разновидностью классов: подобно классам, они инкапсулируют поля и методы, но не обладают свойствами наследования и полиморфизма.
0 коммент.:
Отправить комментарий