Ответ 1
Это зависит от того, что T
. Если T
является ссылочным типом (то есть a class
), тогда в словаре будет храниться только ссылка. Если T
- тип значения (a struct
), то копия будет сохранена.
У меня есть довольно простой вопрос о хранении данных и его памяти.
У меня есть List<t>
, в котором хранятся базовые объекты, которые мне нужны. Тип t имеет int id, чтобы определить его вместе с другими полями.
Теперь у меня есть словарь. Если я создаю Dictionary<t, int>
, где t является объектом для значения, будет ли распределение памяти намного выше, если я создам Dictionary<int, int>
, то есть копия t-объекта будет сохранена или будет только привязка к t снова сохранить?
Спасибо
Это зависит от того, что T
. Если T
является ссылочным типом (то есть a class
), тогда в словаре будет храниться только ссылка. Если T
- тип значения (a struct
), то копия будет сохранена.
Типы ссылок не создают повторяющиеся объекты, когда вы их передаете. Под обложками, в основном, вы обходите указатели. Поэтому, если у вас есть N объектов, у вас будет N x память на объект + память, необходимая для ссылки на каждый объект. Это независимо от контейнера хранения для этих ссылок, в вашем случае, словаря. Вы понесете некоторую стоимость памяти для словаря, но если вы создали еще один словарь и поместили в него все те же объекты, у вас было бы только 2x расходы на память словаря плюс один набор объектов в памяти. Это когда вы используете ссылочные типы.
MyObject object = new MyObject(); // one object created in memory
MyObject object2 = object; // still only one object created in memory, but we have two references now
Типы значений всегда уникальны в памяти. Поэтому, если вы создаете словарь System.Int32, а затем создаете дубликат словаря, вы также будете иметь копию каждого значения в словаре.
int myInt = 5; // one int created in memory
int myInt2 = myInt; // two ints have been created in memory
Итак, давайте выясним, какие блоки памяти выделены для определенных сценариев:
// two value types
Dictionary<int, int> myDictionary1 =
1 x Dictionary
N x int <key>
N x int <value>
Dictionary<int, int> myDictionary1 +
Dictionary<int,int> myDictionary2 (clone of 1) =
2 x Dictionary
2N x int <key>
2N x int <value>
// reference types
Dictionary <string, MyObject> myDictionary3 =
1 x Dictionary
N x string Reference
N x string instance (if they are all unique)
N x Object Reference
N x Object instance (if they are all unique)
Dictionary <string, MyObject> myDictionary3 +
Dictionary <string, MyObject> MyDictionary4 (clone of 3) =
2 x Dictionary
2N x string reference
1N x string instance (if they are all unique)
2N x Object reference
1N x Object instance (if they are all unqiue)
Вы сценарий:
Dictionary<int, MyObject> myDictionary5
1 X Dictionary
N X key
N X value reference
N X value object
Dictionary<int, MyObject> myDictionary5 +
Dictionary<int, MyObject> myDictionary6 (clone of 5) =
2 x Dictionary
2N x key
2N x value reference
1N x value objects
Сохраняется только ссылка на ваш объект. Распределение памяти будет небольшим.
Я предполагаю, что вы говорите о конкретном типе коллекции System.Collections.Generic.Dictionary<K,V>
.
Вы не сказали нам, является ли ваш тип 't' типом значения или ссылочным типом.
Если это ссылочный тип, например, class T { int id; ...}
, то Dictionary<K,T>
будет содержать ссылки на добавленные вами объекты.
Если это тип значения, например. struct T { int id; ...}
, то Dictionary<K,T>
сохранит копии добавленных значений.
Счастливый взлом.
Как я упоминал в другом вопросе для профилирования памяти при разработке, вы можете использовать этот код:
bool forceFullCollection = false;
Int64 valTotalMemoryBefore = System.GC.GetTotalMemory(forceFullCollection);
//call here your bulk of Dictionary operations and objects allocations
Int64 valTotalMemoryAfter = System.GC.GetTotalMemory(forceFullCollection);
Int64 valDifferenceMemorySize = valTotalMemoryAfter - valTotalMemoryBefore;
О параметре forceFullCollection: "Если параметр forceFullCollection равен true, этот метод ждет короткий интервал перед возвратом, когда система собирает мусор и завершает объекты. Длительность интервала - это внутренний заданный предел по количеству циклов сбора мусора и изменению объема памяти, восстановленного между циклами. Сборщик мусора не гарантирует, что будет собрана вся недоступная память". Метод GC.GetTotalMemory
Удачи!;)