说我有这个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 ++(我的主要工具),所以我不能忽视这一点,我的意思是它真的毁了我这里的乐趣(:
答案 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类中是引用类型,结构是值类型。
如果你真的想要在堆栈上分配类型,你可以创建一个结构。但是有几个原因不能:
最后,在堆上分配小对象没有任何内在的坏处。内存管理器实际上是专门为有效处理小型短期对象而设计的。
这是一个代码示例,如果它是一个结构,它不起作用,但如果它是一个类,它可以正常工作:
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);