Структуры всегда выделяются в стеке, а иногда - в куче? - PullRequest
36 голосов
/ 31 января 2011

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

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);
}

Ответы [ 6 ]

55 голосов
/ 31 января 2011

Во-первых, прочитайте этот пост от Эрика Липперта на Стек - это деталь реализации .Следуйте за ним Правда о типах значений .Что касается вашего конкретного вопроса

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

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

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

Вы думаете об этом правильно, и это один из важных моментов, где может быть назначен тип значения.См. Второй пост, на который я ссылался в «Правде о типах значений», для более подробной информации.Но просто помните, что The Stack - это деталь реализации.Главное, что вам не нужно беспокоиться об этом.Вы должны быть обеспокоены семантической разницей между типами значений и ссылочными типами.

16 голосов
/ 31 января 2011

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

5 голосов
/ 14 февраля 2013

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

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

2 голосов
/ 31 января 2011

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

1 голос
/ 16 февраля 2013

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

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

1 голос
/ 31 января 2011

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

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

Дайте мне знать, если я ошибаюсь!

...