Сведения о вопросе

LiKIY

11:50, 4th August, 2020

Теги

.net   memory    

Как управляемая память .net обрабатывает типы значений внутри объектов?

Просмотров: 458   Ответов: 6

public class MyClass
{
    public int Age;
    public int ID;
}

public void MyMethod() 
{
    MyClass m = new MyClass();
    int newID;
}

Насколько я понимаю, верно следующее:

  1. Ссылка m живет в стеке и выходит из области видимости при выходе MyMethod().
  2. Тип значения newID живет в стеке и выходит за пределы области действия при выходе MyMethod().
  3. Объект, созданный оператором new, живет в куче и становится возвращаемым GC, когда MyMethod() завершает работу, предполагая, что никакой другой ссылки на объект не существует.

Вот мой вопрос:

  1. Существуют ли типы значений внутри объектов в стеке или куче?
  2. Является ли бокс / распаковка типов значений в объекте проблемой?
  3. Есть ли какие-либо подробные, но понятные ресурсы по этой теме?

Логически я бы предположил, что типы значений внутри классов будут находиться в куче, но я не уверен, что они должны быть упакованы, чтобы попасть туда.

Редактировать:

Рекомендуемое чтение для этой темы:

  1. CLR через C# Джеффри Рихтер
  2. Важно .NET Дон коробки



  Сведения об ответе

KOMP

11:35, 4th August, 2020

Значения типа Value для класса должны жить вместе с экземпляром объекта в управляемой куче. Стек потока для метода живет только в течение срока действия метода; как может сохраняться значение, если оно существует только в этом стеке?

Размер объекта класса в управляемой куче - это сумма его полей типа значения, указателей ссылочного типа и дополнительных служебных переменных CLR, таких как индекс блока синхронизации. Когда кто-то присваивает значение полю типа значения объекта, CLR копирует это значение в пространство, выделенное внутри объекта для этого поля particluar.

Возьмем, к примеру, простой класс с одним полем.

public class EmbeddedValues
{
  public int NumberField;
}

А вместе с ним и простой тестовый класс.

public class EmbeddedTest
{
  public void TestEmbeddedValues()
  {
    EmbeddedValues valueContainer = new EmbeddedValues();

    valueContainer.NumberField = 20;
    int publicField = valueContainer.NumberField;
  }
}

Если вы используете дизассемблер MSIL, предоставленный платформой .NET SDK, чтобы заглянуть в код IL для EmbeddedTest.TestEmbeddedValues()

.method public hidebysig instance void  TestEmbeddedValues() cil managed
{
  // Code size       23 (0x17)
  .maxstack  2
  .locals init ([0] class soapextensions.EmbeddedValues valueContainer,
           [1] int32 publicField)
  IL_0000:  nop
  IL_0001:  newobj     instance void soapextensions.EmbeddedValues::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  ldc.i4.s   20
  IL_000a:  stfld      int32 soapextensions.EmbeddedValues::NumberField
  IL_000f:  ldloc.0
  IL_0010:  ldfld      int32 soapextensions.EmbeddedValues::NumberField
  IL_0015:  stloc.1
  IL_0016:  ret
} // end of method EmbeddedTest::TestEmbeddedValues

Обратите внимание, что CLR сообщается stfld загруженное значение "20" в стеке в расположение загруженного поля EmbeddValues' NumberField, непосредственно в управляемую кучу. Аналогично, при извлечении значения он использует инструкцию ldfld для прямого копирования значения из этого расположения управляемой кучи в стек потоков. При этих типах операций не происходит никакой распаковки/распаковки коробки.


  Сведения об ответе

prince

08:24, 6th August, 2020

  1. Все ссылки или типы значений, которыми владеет объект, находятся в куче.
  2. Только если вы бросаете Инты на объекты.


  Сведения об ответе

SEEYOU

08:46, 19th August, 2020

Лучший ресурс, который я видел для этого, - это книга CLR через C# Джеффри Рихтера. Это хорошо стоит прочитать, если вы делаете какие-либо разработки .NET. Исходя из этого текста, я понимаю, что типы значений в ссылочном типе действительно живут в куче, встроенной в родительский объект. Ссылочные типы всегда находятся в куче. Бокс и распаковка не симметричны. Бокс может быть более серьезной проблемой, чем распаковка. Для бокса потребуется скопировать содержимое типа значения из стека в кучу. В зависимости от того, как часто это происходит с вами, возможно, нет смысла иметь структуру вместо класса. Если у вас есть какой-то критический для производительности код, и вы не уверены, происходит ли бокс и распаковка, используйте инструмент для изучения кода IL вашего метода. Вы увидите слова box и unbox в IL. Лично я бы измерил производительность моего кода и только потом увидел, является ли это кандидатом на беспокойство. В вашем случае я не думаю, что это будет такой критический вопрос. Вам не придется копировать данные из стека в кучу (поле) каждый раз, когда вы обращаетесь к этому типу значений внутри ссылочного типа. Именно в этом случае бокс становится более значимой проблемой.


  Сведения об ответе

lesha

01:19, 7th August, 2020

  • Ans#1: куча. Коробка перефразирование не с превосходнейшей основных .Net Том 1'

Ссылочные типы (RT) всегда дают экземпляры, выделенные в куче. Напротив, типы значений (VT) зависят от контекста - если локальный var является VT, то CLR выделяет память в стеке. Если поле в классе является членом VT, то CLR выделяет память для экземпляра как часть макета объекта / типа, в котором объявлено поле.

  • Ans#2: нет. Бокс будет происходить только тогда, когда вы обращаетесь к структуре с помощью ссылки на объект / указателя интерфейса. obInstance.VT_typedfield не будет боксировать.

    Переменная RT содержит адрес объекта, на который она ссылается. 2 RT var может указывать на один и тот же объект. Напротив, переменные VT - это сами экземпляры. 2 VT var не может указывать на один и тот же объект (struct)

  • Ans#3: Дон бокс эссенциальный .net / Джеффри Рихтер CLR через C#. у меня есть копия первого... хотя более поздние версии могут быть более обновлены для .Net ревизий


  Сведения об ответе

lool

17:46, 21st August, 2020

Существуют ли типы значений внутри объектов в стеке или куче?

В куче. Они являются частью выделения контура объекта, так же как и указатели для хранения ссылок.

Является ли бокс / распаковка типов значений в объекте проблемой?

Здесь нет никакого бокса.

Есть ли какие-либо подробные, но понятные ресурсы по этой теме?

+1 голос за книгу Рихтера.


  Сведения об ответе

qwerty101

06:30, 24th August, 2020

Переменная или другое место хранения типа структуры-это совокупность открытых и закрытых полей экземпляра этого типа. Дано

struct Foo {public int x,y; int z;}

объявление Foo bar; приведет к тому , что bar.x , bar.y и bar.z будут храниться там, где будет храниться bar . Добавление такого объявления bar в класс с точки зрения компоновки хранилища будет эквивалентно добавлению трех полей int . Действительно, если вы никогда ничего не делали с bar , кроме доступа к его полям , поля bar будут вести себя так же , как и три поля bar_x, bar_y и bar_cantaccessthis_z [доступ к последнему потребует выполнения действий с bar , отличных от доступа к его полям, но он будет занимать пространство, независимо от того, используется ли он вообще для чего-либо].

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться