简体   繁体   中英

How do you store an int or other “C# value types” on the heap (with C#)?

I'm engaged in educating myself about C# via Troelsen's Pro C# book.

I'm familiar with the stack and heap and how C# stores these sorts of things. In C++, whenever we use new we receive a pointer to something on the heap. However, in C# the behavior of new seems different to me:

  • when used with value types like an int, using new seems to merely call the int default constructor yet the value of such an int would still be stored on the stack

I understand that all objects/structs and such are stored on the heap, regardless of whether or not new is used.

So my question is: how can I instantiate an int on the heap? (And does this have something to do with 'boxing'?)

You can box any value type to System.Object type so it will be stored on the managed heap:

int number = 1;
object locatedOnTheHeap = number;

An other question is why you need this.

This is a classic example from the must-know MSDN paper: Boxing and Unboxing (C# Programming Guide)

When the CLR boxes a value type, it wraps the value inside a System.Object and stores it on the managed heap. Boxing is used to store value types in the garbage-collected heap. Boxing is an implicit conversion of a value type to the type object or to any interface type implemented by this value type. Boxing a value type allocates an object instance on the heap and copies the value into the new object.

.

I understand that all objects/structs and such are stored on the heap

BTW, IIRC sometimes JIT optimizes code so value type objects like of type like int are stored in the CPU registers rather than stack.

I do not know why you would want to do this, however, in theory you could indeed box your value. You would do this by boxing the int into an object (which is a reference type and will be placed on the stack:

object IAmARefSoIWillBeOnHeap = (object)1;

*As sll stated, you do not need the (object) as it will be an implicit cast. This is here merely for academic reasons, to show what is happening.

Here is a good article about reference versus value types , which is the difference of the heap versus the stack

yet the value of such an int would still be stored on the stack

This is not necessarily true. Even when it is true, it's purely an implementation detail, and not part of the specification of the language. The main issue is that the type system does not necessarily correlate to the storage mechanism used by the runtime.

There are many cases where calling new on a struct will still result in an object that isn't on the stack. Boxing is a good example - when you box an object, you're basically pushing it into an object (effectively "copying" it to the heap), and referencing the object. Also, any time you're closing over a value type with a lambda, you'll end up "allocating on the heap."

That being said, I wouldn't focus on this at all - the issue really shouldn't about stack vs. heap in allocations, but rather about value type vs. reference type semantics and usage. As such, I'd strongly recommend reading Eric Lippert's The Truth About Value Types and Jon Skeet's References and Values . Both of these articles focus on the important aspects of struct vs. class semantics instead of necessarily looking at the storage.

As for ways to force the storage of an int on the heap, here are a couple of simple ones:

object one = 1; // Boxing
int two = 2; // Gets closed over, so ends up "on the heap"

Action closeOverTwo = () => { Console.WriteLine(two); }
// Do stuff with two here...

var three = new { Three = 3 }; // Wrap in a value type...

A value type is "allocated" wherever it is declared:

  • As a local variable, typically on the stack (but to paraphrase Eric Lippert, the stack is an implementation detail, I suggest you read his excellent piece on his blog: The Truth About Value Types .)
  • As a field in a class, it expands the size of the instance with the size of the value type, and takes up space inside the instance

As such, this code:

var x = new SomeValueType();

does not allocate something on the heap by itself for that value type. If you close over it with an anonymous method or similar, the local variable will be transformed into the field of a class, and an instance of that class will be allocated on the heap, but in this case, the value type will be embedded into that class as a field.

The heap is for instances of reference types.

However, you've touched up something regarding boxing. You can box a value type value to make a copy of it and place that copy on the heap, wrapped in an object.

So this:

object x = new SomeValueType();

would first allocate the value type, then box it into an object, and store the reference to that object in x .

If you want an int on the heap, you can do this:

object o = 4;

But basically, you shouldn't want that. C# is designed for you not to think about such things. Here's a good place to start on that: http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx

So my question is: how can I instantiate an int on the heap? (And does this have something to do with 'boxing'?)

Your understanding about objects and structs are correct. When you intialized either an object or a structure it goes on the heap.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM