tags:

views:

248

answers:

8

I am I think ok at algorithmic programming, if that is the right term? I used to play with turbo pascal and 8086 assembly language back in the 1980s as a hobby. But only very small projects and I haven't really done any programming in the 20ish years since then. So I am struggling for understanding like a drowning swimmer.

So maybe this is a very niave question or I'm just making no sense at all, but say I have an object kind of like this:

class Something : IDoer
{
    void Do(ISomethingElse x)
    {
         x.DoWhatEverYouWant(42);
    }
}

And then I do

var Thing1 = new Something();
var Thing2 = new Something();

Thing1.Do(blah);
Thing2.Do(blah);

does Thing1 = Thing2? does "new Something()" create anything? Or is it not much different different from having a static class, except I can pass it around and swap it out etc.

Is the "Do" procedure in the same location in memory for both the Thing1(blah) and Thing2(blah) objects? I mean when executing it, does it mean there are two Something.Do procedures or just one?

+5  A: 

No they are not the same. They are two separate instances of the class Something. They happen to be identically instantiated, that is all.

David M
But what's this thing actually in memory? Behind the reference, there is a pointer, which points to the state of the object in memory. So where does it point to?
Stefan Steinegger
It's great that you want this level of detail, but it's hard to answer in that much detail here. However, I can recommend an excellent book which will answer your questions from a .NET point of view, which is Jeffrey Richter's CLR via C#.
David M
I think Brian Gideon answered this.
Stefan Steinegger
Agreed - still recommend that book though if you're interested in that level of detail, it's excellent...
David M
A: 

Thing1 != Thing2
These are two different objects in memory.

The Do method code is in the same place for both objects. There is no need to store two different copies of the method.

Itay
+4  A: 

You would create 2 "empty" objects, there would be a small allocation on the heap for each object.

But the "Do" method is always in the same place, that has nothing to do with the absence of state. Code is not stored 'in' a class/object. There is only 1 piece of code corresponding to Do() and it has a 'hidden' parameter this that points to the instance of Something it was called on.

Henk Holterman
+12  A: 

They are two separate objects; they just don't have state.

Consider this code:

var obj1 = new object();
var obj2 = new object();

Console.WriteLine(object.ReferenceEquals(obj1, obj2));

It will output False.

Just because an object has no state doesn't mean it doesn't get allocated just like any other object. It just takes very little space (just like an object).

In response to the last part of your question: there is only one Do method. Methods are not stored per instance but rather per class. If you think about it, it would be extremely wasteful to store them per instance. Every method call to Do on a Something object is really the same set of instructions; all that differs between calls from different objects is the state of the underlying object (if the Something class had any state to begin with, that is).

What this means is that instance methods on class objects are really behaviorally the same as static methods.

You might think of it as if all instance-level methods were secretly translated as follows (I'm not saying this is strictly true, just that you could think of it this way and it does kind of make sense):

// appears to be instance-specific, so you might think
// it would be stored for every instance
public void Do() {
    Do(this);
}

// is clearly static, so it is much clearer it only needs
// to be stored in one place
private static Do(Something instance) {
    // do whatever Do does
}

Interesting side note: the above hypothetical "translation" explains pretty much exactly how extension methods work: they are static methods, but by qualifying their first parameter with the this keyword, they suddenly look like instance methods.

Dan Tao
would like to see an eric lippert response to that. I suspect that because the class is not sealed and it inherits from an interface that there will be some memory for some kind of virtual method pointer ... the point is that his last question is really interesting but requires scary knowldge.
John Nicholas
Please see my comment to David M
Stefan Steinegger
... and is a separate question from the one asked here.
Lasse V. Karlsen
@John: Good point -- "same amount" was pretty presumptuous of me to say (not knowing personally). My point was just that it doesn't require a lot because, obviously, as with an instance of `object`, there's no state. Then again, I wouldn't be surprised if the memory requirements are the same: after all, `object` isn't sealed, either (nor *could* it be), and implementation of an interface is a class-level characteristic, not an instance-level one.
Dan Tao
@Lasse V. Karlsen: IMO, this is exactly the question here: what will actually be in memory where the reference is pointing to? (cit. "does "new Something()" create anything?")
Stefan Steinegger
@Stefan: See Brian Gideon's answer for an excellent response to what you're asking (if I understand you correctly).
Dan Tao
+6  A: 

There are most definitely two different objects in memory. Each object will consume 8 bytes on the heap (at least on 32-bit systems); 4 for the syncblock and 4 for the type handle (which includes the method table). Other than the system-defined state data there is no other user-defined state data in your case.

There is a single instance of the code for the Something.Do method. The type handle pointer that each object holds is how the CLR locates the different methods for the class. So even though there are two different objects in memory they both execute the same code. Since Something.Do was declared as an instance method it will have a this pointer passed to it internally so that the code can modify the correct instance members depending on which object was invoking the method. In your case the Something class has no instance members (and thus no user-defined state) and so this is quite irrelevant, but still happens nevertheless.

Brian Gideon
A: 

Each reference type (Thing1, Thing2) is pointing to a different physical address in main memory, as they have been instantiated separately. The thing pointed to in memory is the bytes used by the object, whether it has a state or not (it always has a state, but whether it has a declared/initialised state).

If you assigned a reference type to another reference type (Thing2 = Thing1;) then it would be the same portion of memory used by two different reference types, and no new instantiation would take place.

AlexW
+1  A: 

Conceptually, Thing1 and Thing2 are different objects, but there is only one Something.Do procedure.

The .Net runtime allocates a little bit of memory to each of the objects you create - one chunk to Thing1 and another to Thing2. The purpose of this chunk of memory is to store (1) the state of the object and (2) a the address of any procedures that that belong to the object. I know you don't have any state, but the runtime doesn't care - it still keeps two separate references to two separate chunks of memory.

Now, your "Do" method is the same for both Thing1 and Thing2, do the runtime only keeps one version of the procedure in memory.

he memory allocated Thing1 includes the address of the the Do method. When you invoke the Do method on Thing1, it looks up the address of its Do method for Thing1 and runs the method. The same thing happens with the other object, Thing2. Although the objects are different, the same Do method is called for both Thing1 and Thing2.

What this boils down to is that Thing1 and Thing2 are different, in that the names "Thing1" and "Thing2" refer to different areas of memory. The contents of this memory is he same in both cases - a single address that points to the "Do" method.

Well, that's the theory, anyway. Under the hood, there might be some kind of optimisation going on (See http://www.wrox.com/WileyCDA/Section/CLR-Method-Call-Internals.id-291453.html if you're interested), but for most practical purposes, what I have said is the way things work.

Kramii
A: 

A good way of think of the new constructor(), is that you are really just calling the method inside your class whos sole responsibility is to produce you a new instance of an object that is cookie cutted from your class.

so now you can have multiple instances of the same class running around at runtime handling all sorts of situations :D

as far as the CLR, you are getting infact 2 seperate instances on memory that each contain pointers to it, it is very similar to any other OOP language but we do not have to actually interact with the pointers, they are translated the same as a non reference type, so we dont have to worry about them!

(there are pointers in C# if you wish to whip out your [unsafe] keyword!)

Gnostus