house = new Building(); // распределить память для объекта типа Building
В первой строке объявляется переменная house
в виде ссылки на объект типа Building
. Следовательно, house
— это переменная, которая может ссылаться на объект, хотя сама она не является объектом. А во второй строке создается новый объект типа Building
, и ссылка на него присваивается переменной house. В итоге переменная house
оказывается связанной с данным объектом.
То обстоятельство, что объекты классов доступны по ссылке, объясняет, почему классы называются
int х;
х = 10;
переменная х содержит значение 10, поскольку она относится к типу int
, который является типом значения. Но в строке
Building house = new Building();
переменная house содержит не сам объект, а лишь ссылку на него.
Переменные ссылочного типа и присваивание
В операции присваивания переменные ссылочного типа действуют иначе, чем переменные типа значения, например типа int
. Когда одна переменная типа значения присваивается другой, ситуация оказывается довольно простой. Переменная, находящаяся в левой части оператора присваивания, получает копию значения переменной, находящейся в правой части этого оператора. Когда же одна переменная ссылки на объект присваивается другой, то ситуация несколько усложняется, поскольку такое присваивание приводит к тому, что переменная, находящаяся в левой части оператора присваивания, ссылается на тот же самый объект, на который ссылается переменная, находящаяся в правой части этого оператора. Сам же объект не копируется. В силу этого отличия присваивание переменных ссылочного типа может привести к несколько неожиданным результатам. В качестве примера рассмотрим следующий фрагмент кода.
Building house1 = new Building();
Building house2 = house1;
На первый взгляд, переменные house1 и house2
ссылаются на совершенно разные объекты, но на самом деле это не так. Переменные house1
и house2
, напротив, ссылаются на один и тот же объект. Когда переменная house1
присваивается переменой house2
, то в конечном итоге переменная house2
просто ссылается на тот же самый объект, что и переменная house1.
Следовательно, этим объектом можно оперировать с помощью переменной house1
или house2
. Например, после очередного присваивания
house1.Area = 2600;
оба метода WriteLine()
Console.WriteLine(house1.Area);
Console.WriteLine(house2.Area);
выводят одно и то же значение: 2600.
Несмотря на то что обе переменные, house1
и house2
, ссылаются на один и тот же объект, они никак иначе не связаны друг с другом. Например, в результате следующей последовательности операций присваивания просто изменяется объект, на который ссылается переменная house2
.
Building house1 = new Building();
Building house2 = housel;
Building house3 = new Building();
house2 = house3; // теперь обе переменные, house2 и house3,
// ссылаются на один и тот же объект.
После выполнения этой последовательности операций присваивания переменная house2
ссылается на тот же самый объект, что и переменная house3
. А ссылка на объект в переменной house1
не меняется.
Методы
Как пояснялось выше, переменные экземпляра и методы являются двумя основными составляющими классов. До сих пор класс Building
, рассматриваемый здесь в качестве примера, содержал только данные, но не методы. Хотя классы, содержащие только данные, вполне допустимы, у большинства классов должны быть также методы.
Метод состоит из одного или нескольких операторов. В грамотно написанном коде C# каждый метод выполняет только одну функцию. У каждого метода имеется свое имя, по которому он вызывается. В общем, методу в качестве имени можно присвоить любой действительный идентификатор. Следует, однако, иметь в виду, что идентификатор Main()
зарезервирован для метода, с которого начинается выполнение программы. Кроме того, в качестве имен методов нельзя использовать ключевые слова С#.