Подтвердить что ты не робот

Всегда ли Structs выделяют выделенные или иногда кучу?

У меня создалось впечатление, что в С# элементы структуры выделяются в стеке и, таким образом, исчезают при возврате из метода, в котором они были созданы. Но что произойдет, если я поместим структурные значения в список и верну это? Элементы выживают. Являются ли экземпляры структуры иногда выделенными в куче?

internal struct Stru
{
  public int i;
}

internal class StruTry
{
  public List<Stru> Get(int max)
  {
    var l = new List<Stru>();
    for (int i = 0; i < max; i++)
      l.Add(new Stru {i=i});

    return l;
  }
}

печать кода 0, 1, 2

[Test]
public void T()
{
  var ll = new StruTry().Get(3);
  foreach (var stru in ll)
    Console.WriteLine("* "+ stru.i);
}
4b9b3361

Ответ 1

Сначала прочитайте это сообщение от Эрика Липперта на The Stack - это описание реализации. Следуйте за ним с помощью Истина о типах значений. Что касается вашего конкретного вопроса

Являются ли экземпляры структуры иногда выделенными в куче?

Да, они иногда выделяются в кучу. Есть много примеров того, когда они могут быть выделены в кучу. Если они помещены в бокс или являются полями в классе или являются элементами массива или являются значением переменной типа значения, которая была закрыта, и т.д.

Но что произойдет, если я поместил структурные значения в список и вернул бы это? Элементы выживают.

Вы думаете об этом правильно, и это одна из основных точек, где может быть выделен тип значения. См. Второе сообщение, которое я упомянул в разделе "Истина о типах значений" для получения более подробной информации. Но просто держите Stack в деталях реализации. Ключевым выводом является то, что вам действительно не нужно беспокоиться об этом. Вы должны быть заинтересованы в семантической разнице между типами значений и ссылочными типами.

Ответ 2

Структуры подобны ints. Если у вас есть локальный int, он обычно находится в стеке, если у вас есть список ints, они хранятся непосредственно в внутреннем массиве списка, который находится в куче. Структуры ведут себя одинаково.

Ответ 3

Но что произойдет, если я поместил структурные значения в список и вернул бы это? Элементы сохраняются.

Технически значения, добавленные в "Список", не являются одинаковыми значениями, они являются копиями на основе значений. Если, например, вы измените оригинал, эти изменения не будут перенесены в копию в списке. Кроме того, "Список" возвращает копию значения по указанному индексу. Это означает, что если структура изменена и вы измените значение, возвращаемое из "Списка", то значение в List<t> останется неизменным. Это не относится к массивам, поскольку индекс массива обеспечивает доступ к фактической переменной.

Ответ 4

Все типы могут быть распределены в куче. Кроме того, heap/stack является деталью реализации CLR, а не спецификацией С#, поэтому вы никогда не должны полагаться на такие вещи. См. здесь для хорошего сообщения в блоге по этому вопросу.

Ответ 5

Из того, что я помню...

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

Сообщите мне, если я ошибаюсь!

Ответ 6

Место хранения (переменная, поле, параметр, слот массива и т.д.) типа struct хранит в нем публичные и частные поля struct. Если это место хранения находится в стеке, поля структуры будут находиться в стеке. Если он находится внутри другого класса или структуры, поля структуры будут храниться как часть этого другого экземпляра класса или структуры.

Место хранения типа класса содержит ссылку на полный объект класса, который всегда либо (1) хранится где-то полностью отдельно от места хранения, содержащего ссылку, или (2) объект класса, местом хранения которого является поле.