Вопрос:

Значение словаря C # очищается, когда я очищаю список, ранее назначенный ему .... почему?

c# dictionary

4419 просмотра

6 ответа

414 Репутация автора

Dictionary <string, List <SaleItem>> saleItemNew = new Dictionary<string, List<    SaleItem>> ();

saleItems = new List <SaleItem> ();

saleItemNew.Add("1", saleItems);

На данный момент список в словаре имеет значения.

saleItems.Clear();

Однако, когда я очищаю список, ранее назначенный ему, значение словаря List теперь пусто ... почему?

Автор: Dano Источник Размещён: 18.06.2009 07:57

Ответы (6)


1 плюс

610490 Репутация автора

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

Это в отличие от типов значений в .Net Framework. Присвоение типа значения по существу выполняет поверхностную копию данных и создает два независимых объекта. Обратите внимание, что если тип значения имеет поле ссылки, два поля в двух типах значений по-прежнему будут указывать на один и тот же объект.

Автор: JaredPar Размещён: 18.06.2009 08:00

11 плюса

12672 Репутация автора

Решение

Словарь содержит одну и ту же ссылку на список, поэтому изменение списка изменит обе ссылки.

Документация Microsoft о ссылочных типах: http://msdn.microsoft.com/en-us/library/490f96s2.aspx

Автор: jjxtra Размещён: 18.06.2009 08:01

0 плюса

14991 Репутация автора

это связано с использованием памяти и указателями. У вас есть стек и куча при выделении памяти для объектов, эта память - одна куча. Ваша переменная saleItems определена в стеке и указывает на адрес памяти в куче. Ваш словарь также находится в стеке, указывая на кучу.

когда ты сказал:

saleItems = new List<SaleItem>()

переменная saleItems помещается в стек и содержит адрес в памяти, указывающий на расположение данных в куче. Скажем так 0x0100. Теперь вы добавляете новый DictionaryItemв свой словарь. DictionaryItemПомещаются в куче с двумя свойствами, Key и Value. В этом случае, вы добавили saleItemsв Value, так Valueимеет адрес , 0x0100а также. Теперь DictionaryItem.Valueуказывает на ту же память, что и saleItems. Когда вы звоните saleItems.Clear, вы говорите, найти список по адресу 0x0100и удалить все элементы. Таким образом, словарь и переменная становятся пустыми, потому что они указывают на одну и ту же память. То, что вы хотите сделать, это сказать еще saleItems = new List<SaleItem>();раз. Теперь saleItems будет указывать на новый адрес в куче (скажем 0x0200). DictionaryItem.Valueвсе еще указывает на адрес памяти, 0x0100так что вы можете воздействовать на saleItemsпеременную, не затрагивая данные в вашем словаре.

Для получения дополнительной информации о стеках и кучах в c # попробуйте эту статью: http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b348b916

Автор: NerdFury Размещён: 18.06.2009 08:11

0 плюса

18753 Репутация автора

Добавление списка в словарь - просто поверхностная копия ... Новый список с такими же значениями не создается и не добавляется (глубокая копия); скорее ссылка на старый список добавлена.

Автор: Polaris878 Размещён: 18.06.2009 08:33

0 плюса

2011 Репутация автора

Он использует ту же ссылку.

Лучший способ сделать это

Dictionary <string, List <SaleItem>> saleItemNew = new Dictionary<string, List<SaleItem>>();
saleItemNew.Add("1", new List<SaleItem>());

И для очистки

saleItemNew["1"] = new List<SaleItem>(); 
Автор: Yahya Размещён: 19.06.2009 01:43

0 плюса

449 Репутация автора

Поскольку это ссылочный тип, копируется только указатель на значения в памяти, а не сами значения. Вы можете указать желаемое поведение с помощью конструктора:

From dot net perls: // // Копируем словарь во второй объект. // Словарь copy = new Dictionary (словарь);

Автор: chris Размещён: 06.07.2011 06:14
Вопросы из категории :
32x32