Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > Общие вопросы .NET
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.01.2018, 00:46   #1
Sallivan_Bidl
Пользователь
 
Регистрация: 19.08.2014
Сообщений: 16
По умолчанию Разница между ссылочными и значимыми типами и связанные с этим вопросы

Здравствуйте уважаемые форумчане. Есть один не совсем понятный для меня скажем так общетеоретический вопрос, связанный с различием между типами значения и ссылочными типами в .net. Заранее извиняюсь за развернутый вопрос, т.к. не могу изложить его лаконично. Но хотелось бы полной ясности т.к. в литературе не все это отражено так подробно, как мне бы хотелось.
Для отправной точки возьму пример из Альбахари:
С помощью ключевого слова struct можно определить специальный тип значения (рис. 2.1)
public struct Point { public int X, Y;}
Рис.2.1.jpg
Присваивание экземпляра типа значения всегда приводит к копированию экземпляра. Например:
static void Main()
{
Point p1= new Point();
p1.X=7;
Point p2=p1;
Console.WriteLine(p1.X) //7
Console.WriteLine(p2.X) //7
p1.X=9;
Console.WriteLine(p1.X) //9
Console.WriteLine(p2.X) //7
}
На рис. 2.2 видно, что p1 и p2 имеют независимые хранилища
Рис.2.2.jpg
Ссылочный тип сложнее типа значения и предполагает наличие двух частей: объекта и ссылки на этот объект. Содержимое переменной или константы, относящейся к ссылочному типу — это ссылка на объект, который содержит значение. Перепишем тип Point из предыдущего примера в виде класса, а не структуры (рис. 2.3):
public class Point { public int X, Y;}
Рис.2.3.jpg
Присваивание переменной ссылочного типа копирует ссылку, но не экземпляр объекта. Это позволяет множеству переменных ссылаться на один и тот же объект - то, что обычно невозможно с типами значений. Если повторить предыдущий пример при условии, что Point теперь является классом, операция над р1 оказывает влияние на p2:
static void Main()
{
Point pl = new Point() ;
pl.X = 7;
Point p2 = pl; // Копирует ссылку на pl

Console.WriteLine (pl.X); // 7
Console.WriteLine (p2.X); // 7
pl.X = 9; // Изменить pl.X
Console.WriteLine (pl.X); // 9
Console.WriteLine (p2.X); // 9
}
Ha рис. 2.4 видно, что р1 и p2 — это две ссылки, указывающие на один и тот же объект.
Рис.2.4.jpg
Хорошо, с теорией закончили. Дальше сам вопрос. Единственно только отмечу для себя, что на рис. 2.4 p2 получает ссылку не на p1, а на то, что помечено словом объект. Может быть в этом частично и ответ на мой вопрос. Итак вопрос.
Есть следующий простой «учебный» код, писал сам, не критикуйте сильно в т.ч. и за форматирование. Есть три класса (на то, что они private не заостряйте внимания). A и B – совсем примитивные, а класс Identifier – чтобы создать объект-идентификатор - каждый новый создаваемый объект Identifier-а получает на 1 больший ID, чем предыдущий.
private class A
{
public object X;
}

private class B
{
public object Y;
}

private class Identifier
{
private static int count = 0;
public int ID = 0;
public Identifier()
{
count++;
ID = count;
}
}
И вот их использование, скажем в методе Main:
var a = new A();
var b = new B();
var i1 = new Identifier();
var i2 = new Identifier();
var i3 = new Identifier();
a.X = i1;
var c = a.X;
b.Y = a.X;
a.X = i3;
Debug.WriteLine(string.Format("i1={ 0}, i2={1}, i3={2}",i1.ID, i2.ID, i3.ID));
Debug.WriteLine(string.Format("(a.X ).ID={0}, (c=a.X).ID={1}, (b.Y=a.X).ID={2}",
((Identifier)a.X).ID, ((Identifier)c).ID, ((Identifier)b.Y).ID));

И вот результат вывода программы:
i1=1, i2=2, i3=3
(a.X).ID=3, (c=a.X).ID=1, (b.Y=a.X).ID=1
В первой строке я просто проверяю, что мои объекты идентификаторы работают правильно т.е. получают новые ID. Вопрос заключается в следующем: почему при изменении ссылки a.X с объекта i1 на объект-идентификатор i3, другие переменные (c и b.Y) не стали автоматически ссылаться тоже на i3, а остались ссылаться по-прежнему на i1, хотя c=a.X и b.Y=a.X? Может кому-то этот вопрос покажется глупым, но получается что до присваивания a.X = i3, сразу три переменные a.X, c, b.Y ссылались на объект i1, после присваивания a.X = i3, две переменные (с, b.Y) остались ссылаться на i1. Т.е. они изначально ссылались на i1, а не на a.X, так получается? Из этого всего у меня вытекает один важный для меня вопрос из-за которого я и создал эту тему.
Предположим для работы программы нужно создать, инициализировать два класса. Сперва один, скажем FirstClass, который осуществляет первичную обработку (считывание) информации и заполняет данными массивы, списки типа List<T>, другие данные. В процессе работы экземпляра класса FirsClass (firstCl) в нем накапливается значительный объем информации. После обработки этих данных для работы программы необходимо передать часть этой информации в экземпляр SecondClass для ее конечной обработки в соответствие с некоторой специфичной логикой. Так вот вопрос: Если
1) данные из firstCl (например несколько массивов, списков – например list=new List<double[]>()) передаются в экземпляр SecondClass (secondCl). После этого firstCl становится «ненужным»
2) затем на firstCl вызывается метод Dispose класса FirstClass (а в Dispose скажем вызывается метод list.Clear())
3) будут ли данные, переданные из firstCl в secondCl, например ссылка на тот же list в каком-нибудь private поле SecondClass-а все еще доступными в нормальном (не обнуленном) виде объекту secondCl?
Или после выполнения firstCl.Dispose() эти данные потеряются(получат ссылки на null) и в экземпляре secondCl. По логике ничего такого боятся не стоит, но хотелось бы узнать у "знающих".
Спасибо за ответ!

Последний раз редактировалось Sallivan_Bidl; 02.01.2018 в 00:50.
Sallivan_Bidl вне форума Ответить с цитированием
Старый 02.01.2018, 23:36   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Сообщение от Sallivan_Bidl Посмотреть сообщение
2) затем на firstCl вызывается метод Dispose класса FirstClass (а в Dispose скажем вызывается метод list.Clear())
IDisposable обычно реализуется для владельцев неуправляемых ресурсов. или значительного объема памяти.

Цитата:
Сообщение от Sallivan_Bidl Посмотреть сообщение
3) будут ли данные, переданные из firstCl в secondCl, например ссылка на тот же list в каком-нибудь private поле SecondClass-а все еще доступными в нормальном (не обнуленном) виде объекту secondCl?
List<T> тоже класс, а не структура, потому после list.Clear вы теряете данные.

в данном случае вы можете просто FirstClass передать внутрь SecondClass.


Цитата:
Сообщение от Sallivan_Bidl Посмотреть сообщение
Т.е. они изначально ссылались на i1, а не на a.X, так получается?
у вас же нарисована что ссылка ведет на объект.
ссылка на ссылку обычно не существует.(разве что ref/out параметры из обыденного)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 03.01.2018, 00:43   #3
Sallivan_Bidl
Пользователь
 
Регистрация: 19.08.2014
Сообщений: 16
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
IDisposable обычно реализуется для владельцев неуправляемых ресурсов. или значительного объема памяти.
В моем случае как раз вариант со значительным объемом памяти, которую хотелось бы по-возможности освободить. Передавать весь объект другому как-то не хочется т.к. в firstCl много всякого ненужного, много полей инициализируются
"сырыми" данными, нужными только внутри методов самого класса.
Пришла в голову мысль, если в том же методе Dispose сделать например не list.Clear(), а list=null, т.е. я занулю ссылку самой переменной list в объекте firstCl и что при этом произойдет: я просто потеряю ссылку на список? А поскольку у меня на сам лист есть ссылка в другом объекте (secondCl - например в переменной listSecCl), то listSecCl не будет null, или будет? Видимо надо проверить на практике.

Последний раз редактировалось Sallivan_Bidl; 03.01.2018 в 02:48.
Sallivan_Bidl вне форума Ответить с цитированием
Старый 03.01.2018, 12:57   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
Сообщение от Sallivan_Bidl Посмотреть сообщение
то listSecCl не будет null, или будет?
не будет, с чего вдруг?
сами ссылки не связаны, у вас же на диаграмме 4 нет связей между ссылками
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 04.01.2018, 06:09   #5
Sallivan_Bidl
Пользователь
 
Регистрация: 19.08.2014
Сообщений: 16
По умолчанию

Спасибо, теперь вроде все понял.
Sallivan_Bidl вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Разница между числами businessman Паскаль, Turbo Pascal, PascalABC.NET 6 21.05.2015 12:55
разница между компами новая Компьютерное железо 1 20.11.2011 12:33
В чем разница между С и С++? Freddy Krjuger Общие вопросы C/C++ 1 14.11.2009 21:23
Разница между датами kykysya Общие вопросы Delphi 8 26.03.2009 18:22