我想用C#在堆栈上分配一个对象

时间:2010-11-05 00:10:03

标签: c# memory-management

说我有这个C#类:

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

如何在函数内声明它的对象,该对象将在堆栈​​上而不是在堆上分配?
换句话说,我想避免对此使用'new'关键字。此代码错误

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

我知道堆栈/堆是完美的,我听说过很棒的C#GC,但我坚持要在堆栈中分配这个小对象,这只是为了方便起见。

这种态度来自C ++(我的主要工具),所以我不能忽视这一点,我的意思是它真的毁了我这里的乐趣(:

4 个答案:

答案 0 :(得分:11)

你不能(也不应该)这样做。即使您使用struct(将放在堆栈中),您也必须使用new运算符来包含类。严肃地说,如果你换成另一种语言,也要改变你的态度。

答案 1 :(得分:9)

如果使用struct将其更改为值类型并在方法体内创建新实例,则会在堆栈上创建它。但是,成员,因为它们是引用类型仍将在堆上。无论是值还是引用类型的语言仍然需要new运算符,但您可以使用var来消除类型名称的双重使用

var ctx = new HttpContextEx(); 

否则,按照原样使用C#,因为GC做得很好。

答案 2 :(得分:3)

你必须来自C ++。事情在.Net中不起作用。

所有引用类型都在托管堆上分配,由GC跟踪它们。对于由快速退出的函数确定范围的对象引用,分配的对象很可能仅保留在托管堆的第0代中,这导致非常有效的内存集合。 Managed Heap被调整为处理像这样的短期对象。它甚至没有与您可能习惯的C ++堆相同的分配策略。

这就是CLR的工作原理。如果您想以其他方式工作,请尝试非托管运行时。

答案 3 :(得分:1)

在.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);