locked
Scope of Returned Variables RRS feed

  • Question

  • I've got this function call

    Object obj = Function1();

    public object Function1()

    {

       object myObject = null;

       myObject = Conatiner["UserName"];

     return myObject;

    }

    So the question, myObject is defined in a procedure, and then returned.  Since myObject is defined locally, isn't it destroyed once I leave scope of Function1 ?

     

    Tuesday, May 10, 2011 8:30 PM

Answers

  • Nope, most types in C# (except primitives/structs) are reference types.  Think of them as pointers.  The POINTER myObject (which contains the address to the actual instance) gets destroyed.  But the object itself still lives.  That address gets returned and placed into obj, so it now points to the same instance that was originally in myObject.

     

    Until all references to an instance (obj and myObject) go out of scope, the underlying object will remain valid.

    Tuesday, May 10, 2011 8:36 PM
  • So long as a reference exists to an object, the object is not destroyed.  In fact, in your example, even if you reset myObject to null before returning, the object would not be destroyed, because Container["UserName"] (presuming its a collection of some sort) ALSO has a reference to the object.  In this example, you're just making another reference to the same thing that Container["UserName"] is pointing to, then passing the reference out.
    Tuesday, May 10, 2011 8:45 PM
  • When you create an object in C#, you do it in 2 steps. First, you declare a reference (which is stored on the stack), then you actually create the object itself (which is allocated on the heap).

    object myObject;   // This just creates a reference variable on the stack. It doesn't point to anything, and the object doesn't actually exist yet.

    myObject = new Object();  // Here the object is created on the heap, and the myObject reference is updated to point to it.

    You have to keep these two ideas logically separate in your head. When we talk about something going "out of scope" what we mean is that the reference which is allocated on the stack goes out of scope. The object on the heap doesn't have any logical scope - it is just sitting out there. You're right that your myObject reference goes out of scope and no longer exists after Function1 is finished, but you created a new reference on the stack (obj) which points to the same object on the heap. So long as any reference to an object still exists somewhere, the garbage collector will leave the object on the heap alone.

    As an added bit of confusion, value types work slightly differently. If you were to modify your method like so:

    int myInt = Function1();
    
    public int Function1()
    {
        int myInnerInt = 100;
        return myInnerInt;
    }
    

    Int32 (int) is a value type, so space on the heap is never allocated for it. The whole thing is stuck right on the stack. In this case, when Function1 is finished executing, myInnerInt no longer exists. It is destroyed - there's nothing on the stack, there are no references. But, just before it is destroyed, it is copied and pasted into myInt. In this case, myInt is not a reference to the same thing as myInnerInt, but it is a separate copy of it.

    All of these things take awhile to wrap your mind around, but understanding them will save a lot of hours of troubleshooting in the future.

    Tuesday, May 10, 2011 8:51 PM

All replies

  • Nope, most types in C# (except primitives/structs) are reference types.  Think of them as pointers.  The POINTER myObject (which contains the address to the actual instance) gets destroyed.  But the object itself still lives.  That address gets returned and placed into obj, so it now points to the same instance that was originally in myObject.

     

    Until all references to an instance (obj and myObject) go out of scope, the underlying object will remain valid.

    Tuesday, May 10, 2011 8:36 PM
  • So long as a reference exists to an object, the object is not destroyed.  In fact, in your example, even if you reset myObject to null before returning, the object would not be destroyed, because Container["UserName"] (presuming its a collection of some sort) ALSO has a reference to the object.  In this example, you're just making another reference to the same thing that Container["UserName"] is pointing to, then passing the reference out.
    Tuesday, May 10, 2011 8:45 PM
  • When you create an object in C#, you do it in 2 steps. First, you declare a reference (which is stored on the stack), then you actually create the object itself (which is allocated on the heap).

    object myObject;   // This just creates a reference variable on the stack. It doesn't point to anything, and the object doesn't actually exist yet.

    myObject = new Object();  // Here the object is created on the heap, and the myObject reference is updated to point to it.

    You have to keep these two ideas logically separate in your head. When we talk about something going "out of scope" what we mean is that the reference which is allocated on the stack goes out of scope. The object on the heap doesn't have any logical scope - it is just sitting out there. You're right that your myObject reference goes out of scope and no longer exists after Function1 is finished, but you created a new reference on the stack (obj) which points to the same object on the heap. So long as any reference to an object still exists somewhere, the garbage collector will leave the object on the heap alone.

    As an added bit of confusion, value types work slightly differently. If you were to modify your method like so:

    int myInt = Function1();
    
    public int Function1()
    {
        int myInnerInt = 100;
        return myInnerInt;
    }
    

    Int32 (int) is a value type, so space on the heap is never allocated for it. The whole thing is stuck right on the stack. In this case, when Function1 is finished executing, myInnerInt no longer exists. It is destroyed - there's nothing on the stack, there are no references. But, just before it is destroyed, it is copied and pasted into myInt. In this case, myInt is not a reference to the same thing as myInnerInt, but it is a separate copy of it.

    All of these things take awhile to wrap your mind around, but understanding them will save a lot of hours of troubleshooting in the future.

    Tuesday, May 10, 2011 8:51 PM
  • Thanks for al the replies.  They were all helpful.
    Tuesday, May 10, 2011 9:25 PM
  • Glad to help!

    Don't forget to mark answers or vote supporting posts as helpful in pointing you the right direction.

    Tuesday, May 10, 2011 9:58 PM