6

First of all I apologize if it sounds too dumb. but I always find myself asking the following questions.

Since object class is the ultimate base class for all classes in .Net and class is a reference type, reference types are stored on heap so how did anything even get to the stack. I know primitive types get stored on stack and that's where I get confused.

Take int32 for instance, if its a class and its base class is object, then its a reference type, should be on heap. How does it go to stack.

If its not a class then how can we do this

int i = 1;
object obj = i;  

Since I cannot do something like

int i = 1;
MyClass myObj = i;

Edit

From the answers I got, int is struct rather than class. Still the confusion is how a value type's base class is a reference type (object) and its a value type not a reference type.

Another point that came up is that "value-types that belong to a class do not get stored on the stack", I guess everything is inside a class, even the Main method inside a console Program. For me that means all the variable somehow belong to a class? So How do they go to stack?

ZedBee
  • 2,320
  • 7
  • 39
  • 61
  • 1
    A value types inherits from type `System.Object` but that does not mean that it inherits from a class. Types and classes are different things. – Rodrick Chapman Feb 03 '14 at 06:43
  • @RodrickChapman System.Object is a class. How is Type and class different in this case? – ZedBee Feb 03 '14 at 06:51
  • 1
    `classes` and `structs` are how you *define* types, but you don't inherit from classes or structs, you inherit from types. – Rodrick Chapman Feb 03 '14 at 07:05

5 Answers5

15

First of all I apologize if it sounds too dumb. but I always find myself asking the following questions.

These are very common questions.

Since object class is the ultimate base class for all classes in .Net and class is a reference type, reference types are stored on heap so how did anything even get to the stack.

You are confusing many things. Let's start with:

  • An instance of a value type is a value.
  • A reference is a value.
  • A reference refers to an instance of a reference type. (Or it is null, in which case it refers to nothing.)

OK, so now we know that there are three kinds of things, and two of them are values.

So now let's state your sentence correctly:

The object class is the ultimate base class for all classes in .NET. All instances of classes are instances of reference types. All instances of reference types are stored on heap. How is anything stored on the stack?

Now that we have the question phrased correctly the answer is clear. References and instances of value type can go on the stack.

Let's move on.

I know primitive types get stored on stack and that's where I get confused.

Banish the word "primitive type" from your vocabulary; it is meaningless. Let's rephrase:

I know that instances of value types get stored on stack

No, you do not know that because in order to count as knowledge a statement must be true. That statement is false. Values get stored in variables. Variables are either long-lived or short-lived. Short-lived variables go on the stack. Long-lived variables go on the heap.

Take int32 for instance, if its a class and its base class is object, then its a reference type, should be on heap.

Int32 is not a class. It's a struct. It is not a reference type.

Still the confusion is how a value type's base class is a reference type (object) and its a value type not a reference type.

Mary is a mother. She is female. Are all her children therefore also female?

How does it go to stack.

An integer goes on the stack when the integer is stored in a short-lived variable.

A reference goes on the stack when the reference is stored in a short-lived variable.

Whether a value is a reference or an instance of value type is irrelevant; what matters is how long does the variable live?

If its not a class then how can we do this

int i = 1;
object obj = i;  

Good question. A special class is generated. Think of this as being:

class BoxedInt 
{
    int value;
    public BoxedInt(int v) { this.value = v; }
    public int Unbox() { return this.value; }
}

So then your program fragment is:

int i = 1;
object obj = new BoxedInt(i);

And then

int j = (int)obj;

is the same as

int j = ((BoxedInt)obj).Unbox();

Another point that came up is that "value-types that belong to a class do not get stored on the stack

A better way to say that is: fields of a reference type are long-lived variables. Therefore they are stored on the heap.

I guess everything is inside a class, even the Main method inside a console Program.

Yes, all code is inside a class or struct.

For me that means all the variable somehow belong to a class?

No, a local variable is not a member of a class.

I live in a yellow house. Are all the objects inside of it also therefore yellow?

So How do they go to stack?

A local variable in an ordinary method is short-lived, so it goes on the stack.

Simply stop thinking about the stack as having something to do with what kind of data is being stored. The stack has nothing whatsoever to do with what kind of data is being stored. Think about variables. The stack is the place for short-lived variables. The heap is the place for long-lived variables. The type of the variable is irrelevant.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • Eric: I am curious what you mean when you say that the notion of primitive types is "meaningless." I grant you that the distinction is not relevant to this question, but do you mean it more generally? Both the C# language specification and the .NET Framework documentation mention them and I'm curious whether I'm missing some greater point that you're making. – Cole Campbell Feb 03 '14 at 19:04
  • @ColeCampbell: The C# specification uses the term once without definition, so it is not a useful term in that context. "Meaningless" is perhaps too strong; let me rather say: what is the compelling usage case for an "is this type primitive?" predicate? Under what circumstances would you use such a predicate to make a decision in a realistic program? – Eric Lippert Feb 03 '14 at 20:34
  • I was tempted to say that the distinction is sometimes important to those of us who occasionally dive into the dark underworld of unsafe code. However, if I am being precise, the important question there is not whether the types are _primitive_, but whether they are _blittable_, and while there is a great deal of overlap between the two they aren't quite the same. So I take your point. Thank you for the clarification. – Cole Campbell Feb 03 '14 at 20:52
  • @ColeCampbell: Indeed; `struct S { int x; int y; }` is clearly not primitive, whatever that means, but it definitely is blittable. (Or as the C# specification says, "unmanaged", which is a bit of a misnomer IMO.) – Eric Lippert Feb 03 '14 at 21:38
  • Wow what an answer. Now that's how question should be answered here on SO. Seems like most of what I learned (assumed may be the right word :)) about how variables get stored on stack and heap was wrong. Really helpful. – ZedBee Feb 04 '14 at 06:33
  • @ZedBee: You're welcome! You should read my other articles on this subject, in particular "The Stack Is An Implementation Detail", "The Truth About Value Types" and "Another Myth About Value Types". A great many programmers believe falsehoods about the stack; I am not sure why. – Eric Lippert Feb 04 '14 at 06:36
  • @EricLippert I am already going through your blog. :) Well don't know about others but I don't remember if anybody ever explained the topic in context of short lived and long lived variables. People always talk in terms of Value type and reference types. Though its relevant but not the basic concept how memory is allocated on stack and heap. Now after understanding the short lived and long lived concept, things seem to make sense. :) – ZedBee Feb 04 '14 at 07:10
  • @EricLippert could you please kindly provide links to the articles in your answer, which you mentioned in your comment. – ZedBee Feb 04 '14 at 07:16
1

Int32 is not a class.It is a struct.And structs are specially handled by the compiler.

object obj = i;  

This is called boxing. Because all of the classes are implicitly inherits from object, you can assign anything to object.You should take a look at the documentation for this and also there are thousands of articles about boxing and unboxing on the Internet.

From MSDN:

Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the CLR boxes a value type, it wraps the value inside a System.Object and stores it on the managed heap.

Here are some references that might be useful

  1. struct (C# Reference)
  2. Types (C# Reference)
  3. Value Types and Reference Types
  4. Boxing and Unboxing
  5. The Truth About Value Types - Eric Lippert

- Related Questions

  1. Reference and Value types scenario

  2. What is the difference between a reference type and value type in c#?

Community
  • 1
  • 1
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
1

Int32 is a ValueType and hence it would be allocated in stack. The keyword int refers to the struct System.Int32.


Types in .net are separated into value types and reference types.

Value types are either stack-allocated or allocated inline in a structure.

Reference types are heap-allocated.

Value types consist of two main categories:

  • Structs{bool,Numeric,custom}
  • Enumerations

Both reference and value types are derived from the ultimate base class Object.

In cases where it is necessary for a value type to behave like an object, a wrapper that makes the value type look like a reference object is allocated on the heap, and the value type's value is copied into it. The wrapper is marked so the system knows that it contains a value type. This process is known as boxing, and the reverse process is known as unboxing.

Refer here

Community
  • 1
  • 1
Anirudha
  • 32,393
  • 7
  • 68
  • 89
1

Short answer:

  • The type System.Object is not a "class" but instances of type System.Object are reference types.
  • When type B inherits from type A, the only thing that is implied is that B gets all of A's public or protected non-static methods, properties, and events.
  • Classes are references types and are always allocated on the heap.
  • Structs are value types and may be allocated on the stack, heap, or CPU registers.

Basically, value types can have two different representations in memory (boxed and non-boxed) while reference types only have one kind of representation in memory.


Longer Answer:

First of all, you can absolutely do this:

int i = 1;
MyClass myObj = i;

Just define MyClass as:

class MyClass
{
    int i;
    
    public MyClass(int i)
    {
            this.i = i;
    }
    
    public static implicit operator MyClass(int i)
    {
        return new MyClass(i);
    }
}

(Note well that in this example, the field, i, of the class MyClass is heap-allocated even though it is a value type)

Secondly, value types are not necessarily stored on the stack as in the following cases:

  • Value-typed fields that belong to a class
  • Closed over local value-type variables (i.e. variables captured by a closure)

Now, when type B inherits from type A, that means only that B gets all of A's properties, methods, and events. It does not prescribe how instances of B should be allocated.

Community
  • 1
  • 1
Rodrick Chapman
  • 5,437
  • 2
  • 31
  • 32
  • A gets all of B's public? Or B gets A's public..?? – ZedBee Feb 03 '14 at 06:33
  • Now the point - value-types that belong to a class do not get stored on the stack, I guess everything is inside a class, even the Main method inside a console Program. For me that means all the variable somehow belong to a class? So How do they go to stack? – ZedBee Feb 03 '14 at 07:13
  • The first two sentences are incorrect. `System.Object` is a class. When `B` inherits from `A`, `B` gets all of `A`'s members, regardless of whether they are public, private, protected or internal and regardless of whether they are static or instance. The only things `B` does not get from `A` are constructors and destructors, which are not inheritable. You are confusing whether a member is *inheritable* with whether it is *accessible*; those are two very different things. – Eric Lippert Feb 03 '14 at 20:42
  • Consider for example: `class A { private int x; class B : A { int M() { return this.x; } }`. Just because `x` is private does not mean that it is not *inherited*. – Eric Lippert Feb 03 '14 at 20:44
0

Primitive data types are value type, their size is defined at compile time, so compiler push them on stack for faster access, while reference type are just pointers to starting address of object stored on heap and it's memory is not assigned on compile time(assigned on runtime).

you cannot do

 int i  = null; // Because it's value type and need some value 
 (Default is 0) here int is alias to Int32 which is structure and
  structure is value type and same is for other primitives 
A.T.
  • 24,694
  • 8
  • 47
  • 65