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

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

class Program

{

private static void Main(string[] args)

{

   State state1 = new State();

   State state2 = new State();

       

                          state2.country = new Country();

   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

                              

                          Console.Read();

}

}

struct State

{

public int x;

public int y;

public Country country;

}

class Country

{

public int x;

public int y;

}

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

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

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

class Program

{

static void Main(string[] args)

{

   Person p = new Person { name = "Tom", age=23 };

   ChangePerson(p); 

 

   Console.WriteLine(p.name); // Alice

   Console.WriteLine(p.age); // 23

 

   Console.Read();

}

 

static void ChangePerson(Person person)

{

   // сработает

   person.name = "Alice";

   // сработает только в рамках данного метода

   person = new Person { name = "Bill", age = 45 };

                          Console.WriteLine(person.name); // Bill

}

}

class Person

{

public string name;

public int age;

}

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

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

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

class Program

{

static void Main(string[] args)

{

   Person p = new Person { name = "Tom", age=23 };

   ChangePerson(ref p); 

 

   Console.WriteLine(p.name); // Bill

   Console.WriteLine(p.age); // 45

 

   Console.Read();

}

 

static void ChangePerson(ref Person person)

{

   // сработает

   person.name = "Alice";

   // сработает

   person = new Person { name = "Bill", age = 45 };

}

}

class Person

{

public string name;

public int age;

}

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

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: