so in c++ it\'s very easy. you want whatever class/struct to be allocated on the heap, use new. if you want it on the stack, don\'t use new.
in C# we always use the new
Dont worry about it - you head is still in the c / c++ world where it can matter a lot where things go. There are a bunch of really smart people in CLR team who spend all day worrying about making this magically fast.
There are some gotchas in c# and memory usage usually assocaited with creating lots of tiny object by accidents (doing string = string + other string in a loop is a classic)
There is a memprofiler that will show you whats happening if you really think you have a perf issue caused by memory management
I have written lots of performance intense code (graphics rendering clients, network servers) in c# and never had to worry about any of this
While in the general case it's true that objects are always allocated on the heap, C# does let you drop down to the pointer level for heavy interop or for very high performance critical code.
In unsafe blocks, you can use stackalloc to allocate objects on the stack and use them as pointers.
To quote their example:
// cs_keyword_stackalloc.cs
// compile with: /unsafe
using System;
class Test
{
public static unsafe void Main()
{
int* fib = stackalloc int[100];
int* p = fib;
*p++ = *p++ = 1;
for (int i=2; i<100; ++i, ++p)
*p = p[-1] + p[-2];
for (int i=0; i<10; ++i)
Console.WriteLine (fib[i]);
}
}
Note however that you don't need to declare an entire method unsafe, you can just use an unsafe {...}
block for it.
This is the wrong way to view structs and classes in C#. In C# the difference between a struct and a class is not where it is allocated, but the copy semantics. A struct has value semantics and a class has reference semantics. C++ programmers tend to read more into this, as they are used to objects on the stack having value semantics and objects on the heap having reference semantics.
How this memory is allocated is an implementation detail of the runtime. The runtime can use stacks, heaps, or any other hybrid allocation scheme it likes. While it's true that usually structs will be allocated on something like a stack, and classes will be allocated on some sort of a heap, it is not required. For example, a class allocated in a function and not passed outside the scope of the function could quite easily be allocated on the stack instead.
Don't be fooled by the new
keyword, it's optional for structs.
In C# there is a managed world where you enjoy the Garbage collector and Type-Safety and don't (have to) worry about many memory details. The Stack/Heap difference is irrelevant, it's about copy-semantics.
For those rare cases where you do want control, there is the unsafe (unmanaged) part of C# with real pointers and everything.
But the cost of things are different in C# than they are in C++ so don't hunt ghosts, unmanaged, short lived objects are very cheap. And the compiler can allocate small arrays on the stack as an optimization, you won't be able to tell and neither should you care.
Your explanation of where value types vs. reference types go (stack v. heap) is not completely correct.
Structs can also get allocated on the heap if they are members of a reference type for example. Or if you have boxed them while passing them via an object reference.
You should read http://www.yoda.arachsys.com/csharp/memory.html to get a better understanding of where different types actually are allocated.
On a separate note, in .Net, you really shouldn't care about where a types is allocated - as Eric Lippert writes: the stack is an implementation detail. You are better off understanding the semantics of how types are passed (by value, be reference, etc).
Furthermore, you seem to be making an implication that allocating an object on the heap is more expensive than on the stack. In reality, I would argue that the performance cost of copying value types outweighs the benefit of any savings in a slightly quicker allocation on the stack. The biggest difference between stack and heap, is that on most CPU architectures the stack is more likely to be retained in CPU cache - and thereby avoid cache misses.
This is not the most important issue to be concerned with. You should decide whether the type should have pass-by-value semantics or not. If it doesn't - then perhaps it should be a reference type.