Я хочу разместить объект в стеке с помощью C # - PullRequest
2 голосов
/ 05 ноября 2010

Скажем, у меня есть этот класс C #:

public class HttpContextEx
{
    public HttpContext context = null;
    public HttpRequest req = null;
    public HttpResponse res = null;
}

Как мне объявить его объект внутри функции, которая будет размещена в стеке, а не в куче?
В другихслова, которые я хочу, чтобы не использовать ключевое слово «новый» для этого.Этот код плохой :

HttpContextEx ctx = new HttpContextEx(); // << allocates on the heap!

Я прекрасно знаю, что такое стек / куча, и я слышал о замечательном C # GC, но я настаиваю на выделении этого крошечного объекта, которыйздесь только для удобства, в стеке.

Это отношение исходит от C ++ (мой основной инструмент), поэтому я не могу игнорировать это, я имею в виду, что это действительно разрушает мне удовольствие здесь: (

Ответы [ 4 ]

11 голосов
/ 05 ноября 2010

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

9 голосов
/ 05 ноября 2010

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

var ctx = new HttpContextEx(); 

В противном случае, примите C # какGC делает отличную работу.

3 голосов
/ 05 ноября 2010

Вы должны приехать из C ++. В .Net все не работает так.

Все ссылочные типы размещаются в управляемой куче, где они отслеживаются GC. Для ссылок на объекты, ограниченных функцией, которая быстро завершает работу, выделенные объекты, скорее всего, остаются только в поколении 0 управляемой кучи, и это приводит к очень эффективным коллекциям памяти. Управляемая куча настроена для обработки недолговечных объектов, подобных этому. Он даже не имеет той же стратегии размещения, что и куча C ++, к которой вы привыкли.

Вот как работает CLR. Если вы хотите работать по-другому, попробуйте неуправляемую среду выполнения.

1 голос
/ 05 ноября 2010

В .NET классы являются ссылочными типами, а структуры - типами значений.

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

  • Структуры сложнее реализовать правильно.Вы должны придерживаться классов, пока у вас нет веских оснований для создания структуры.
  • Структуры предназначены для типов, представляющих одну единицу, тогда как ваш тип представляет собой просто контейнер для трех отдельных единиц.
  • Структура не должна быть больше 16 байт для эффективной работы.В 32-битной системе вы попадаете под этот предел, но в 64-битной системе структура больше этого.
  • Структура должна быть неизменной, чтобы работать как тип значения, а ваш тип - нет.

Наконец, нет ничего плохого в выделении небольших объектов в куче.Диспетчер памяти фактически специально разработан для эффективной обработки небольших недолговечных объектов.

Вот пример кода, который не работает, если это структура, но отлично работает, если это класс:

public void SetContext(HttpContextEx ex) {
  ex.context = HttpContext.Current;
  ex.req = ex.context.Request;
  ex.res = es.context.Response;
}

HttpContextEx ctx = new HttpCoontextEx();
SetContext(ctx);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...