Вопрос
Я знаю, что бокс — популярное понятие, о котором доступно множество информации, но у меня есть несколько вопросов, на которые я не могу найти ответы:
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