Вопрос

Я знаю, что бокс — популярное понятие, о котором доступно множество информации, но у меня есть несколько вопросов, на которые я не могу найти ответы:

1) Если упаковка приводит к преобразованию типа значения (структуры) в объект (ссылочный тип) или ссылочный тип, то зачем использовать тип значения, который будет упакован и повлечет за собой снижение производительности?Я знаю о преимуществах и пригодности в определенных случаях структуры или класса.Говорят (1), что значения (типы значений) имеют тенденцию жить в стеке во временном пространстве хранения, но как долго?Если мне не нужен тип, как я могу гарантировать, что о нем позаботятся и утилизируют в этот момент?Или здесь в дело вступает одноразовая выкройка?Я предполагаю, что причина использования структуры будет связана с ее преимуществами.

Интересно, что если я использую структуру для хранения двух строк и поля DateTime, структура будет содержать две ссылки (строки) и DateTime вместе.Я, очевидно, предполагаю, что это происходит быстрее, чем разброс значений.Есть ли что-то, о чем мне нужно знать в этом дизайне?(2).

1) http://en.csharp-online.net/Классы, структуры и объекты — упаковка и распаковка

2) http://dotnetperls.com/Content/Struct-Examples.aspx

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

Спасибо за (потенциальное) образование всем авторам!Пожалуйста, извините за возможную наивность.Изучение внутреннего устройства позволяет мне потратить некоторое время на понимание IL и т. д. (в ближайшее время есть над чем заняться).

Это было полезно?

Решение

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

  • Действуйте как примитивные типы.
  • Иметь размер экземпляра менее 16 байт.
  • Неизменяемы.
  • Семантика значений желательна.

Я также обычно рассматриваю время жизни такой переменной.Если это локальная переменная, используемая внутри метода, я бы предпочел использовать структуру (в противном случае класс).

Другие советы

Вы должны использовать типы значений из-за их логического преимущества, а не повышения производительности. При этом, поскольку типы значений управляются в стеке, нет необходимости участвовать в сборке мусора. Если у вас есть тип, который постоянно создается и отбрасывается (например, int, float, double и т. Д.), Вы можете получить хороший импульс, превратив их в структуры. Остерегайтесь того, что вы должны действительно учитывать это, если вы также можете сделать структуру неизменной.

Пара других вещей, которые следует учитывать -

Во-первых, вы хотите убедиться, что структуры неизменны (в общем). Из-за этого хорошее эмпирическое правило не иметь структур, содержащих ссылочные типы. Строки могут быть исключением из этого, поскольку они неизменны в C #, но с точки зрения общего правила для дизайна, я бы с осторожностью отнесся к этому.

Во-вторых, есть еще один вариант использования для структур, о котором до сих пор не говорилось - большое количество мелких объектов. Если у вас большой список или массив небольших объектов, структуры обеспечивают существенно лучшую когерентность кэша и абсолютно необходимы. Вот почему большинство 3D-движков используют структуры для точек / векторов - они обычно имеют большие массивы точек для вершин и т. Д.

На это стоит обратить внимание, если производительность является важной частью вашего приложения. Например, в одном из моих приложений изменение одного типа с класса на структуру сэкономило 40% времени на длительный (> 5 минут выполнения) процесс. Наличие объектов близко друг к другу в памяти, если вы используете их многократно в сложных математических вычислениях, может дать огромный выигрыш.

Теперь - в вашем случае наличие 2 строк и DateTime, вероятно, не увидят каких-либо улучшений от этого. Типы подпрограмм, которые будут работать со строками, вероятно, не выполняют сложных вычислений (надеюсь), то есть: преобразуют пространство в полмиллиона точек или выполняют матричное решение большого размера и т. Д.

Наконец, вы заметите, что .net3.5sp1 сделал структуры намного более полезными. До 3.5sp1 (на x86) не было встроенных методов с вызовами структуры. Это ограничивало прирост производительности, возможный через структуры. Обновление вашей инфраструктуры может сделать старый структурный код намного, намного быстрее (в некоторых случаях).

Вам не всегда нужен бокс, а с дженериками в этом нет особой необходимости.
Память, используемая типами значений (struct — это тип значения), будет заявлена ​​как
как только метод закончится/вернется, и вы этого не сделаете
нужно сделать что-нибудь, чтобы это произошло.

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

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

GC работает сам по себе, и по большей части вам следует оставить его в покое.
Вы не можете предсказать, когда объект будет удален сборщиком мусора.

Шаблон Dispose используется для ссылочных типов, но не заставляет GC удалять их.
объект.Обычно он используется для освобождения неуправляемых ресурсов.

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


Main
{
   // (0) Stack is empty
   int firstInt = 0;
   // (1) Stack now contains:
   //                     firstInt
   DoSomething1();
   // (7) Stack still contains:
   //                     firstInt
}
// Program ends

DoSomething()
{
   int anInteger = 0; 
   // (2) Stack now contains:
   //                    anInteger
   //                    firstInt
   DoMore()
   // (5) Stack now contains:
   //                     anInteger
   //                     firstInt
}
// (6) anInteger goes out of scope

DoMore
{
  int anotherInteger = 1; 
   // (3) Stack now contains:
   //                     anotherInteger
   //                     anInteger
   //                     firstInt
}
// (4) anotherInteger goes out of scope

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top