Object lifetime

  • Thread starter Thread starter dm_dal
  • Start date Start date
D

dm_dal

Just a quick question regarding object scope and lifetime.

Given the following:

{
DataRow myRow = new DataRow();
...... do some stuff
{
myRow = new DataRow;
..... do some stuff
}
myRow = new DataRow;
..... do some stuff
}

Have I just created three seperate DataRow objects? Or does the assignment
just reassign the original?

dmy
 
That's what I thought. And so the first two instances created are now
marked for deletion and are waiting for GC to process, right?

dmy
 
dmy,

You have created three new DataRow objects. The objects that were
pointed to by myRow then become eligible for GC once the assignment is made
(unless you have compiled for debug mode).

Hope this helps.
 
dm_dal said:
Just a quick question regarding object scope and lifetime.

Given the following:

{
DataRow myRow = new DataRow();
...... do some stuff
{
myRow = new DataRow;
..... do some stuff
}
myRow = new DataRow;
..... do some stuff
}

Have I just created three seperate DataRow objects? Or does the assignment
just reassign the original?

You've created three separate DataRow objects. If you don't pass them
around in some way which keeps a reference elsewhere, each will become
eligible for garbage collection at the time when the next one's
reference is assigned to myRow. (That doesn't mean they'll be collected
immediately, however.)
 
dm_dal said:
That's what I thought. And so the first two instances created are now
marked for deletion and are waiting for GC to process, right?

They're not marked for deletion - they're just *eligible* for
collection. Nothing marks objects as ready to be deleted - the garbage
collector marks things which *shouldn't* be deleted (when it runs) and
then collects everything else (in the generation). (That's a simplistic
view which ignores finalization, admittedly.)
 
Jon said:
You've created three separate DataRow objects. If you don't pass them
around in some way which keeps a reference elsewhere, each will become
eligible for garbage collection at the time when the next one's
reference is assigned to myRow. (That doesn't mean they'll be collected
immediately, however.)

To expand on this a bit...

Strictly speaking, an object referenced by myRow might become eligible
for collection *before* it gets assigned a new object reference. That
can happen if the JIT/Garbage Collector determines that the current
myRow reference is not used at some point before the re-assignment.

For example:

DataRow myRow = new DataRow();

// a) do some stuff

object o = myRow[0]; // get column 0's value

// b) do some other stuff, but not using myRow

myRow = new DataRow;

At any point after execution of the "object = = myRow[0];" statement
(section 'b') the object referenced by myRow can be collected - the GC
doesn't need to wait until the second assignment to myRow.

Normally, this isn't a problem (and I imagine it would not be with the
DataRow object), but I've seen some problems described in the news
groups that were a result of this kind of thing (one was a mutex
intended to signal new instances of the application that never seemed to
function, and the other was a Registry value write that blew up because
the underlying handle got closed by a finalizer called too early).

These problems can be real head scratchers if you don't realize that
object lifetime can be shorter than what you'd guess. I believe that
this issue would only be a true potential problem for objects that have
a finalizer.

Anyway, this is discussed by Chris Brumme in gory detail here:

http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx
 
To expand on this a bit...

Strictly speaking, an object referenced by myRow might become eligible
for collection *before* it gets assigned a new object reference. That
can happen if the JIT/Garbage Collector determines that the current
myRow reference is not used at some point before the re-assignment.

Oh yes, good catch. Here's a sample program to show this happening:

using System;

class Test
{
~Test()
{
Console.WriteLine ("Finalizing");
}

static void Main()
{
Test t = new Test();

Console.WriteLine ("Created first");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Console.WriteLine ("Creating second");
t = new Test();
Console.WriteLine ("Created second");

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Console.WriteLine ("Last reference to t: {0}", t);

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Console.WriteLine ("End of method");
}
}

The output on my box is:

Created first
Finalizing
Creating second
Created second
Last reference to t: Test
Finalizing
End of method

I had expected that the JIT wouldn't be clever enough to spot that -
that it would just have a "first use to last use" policy, but nope -
it's really smart :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top