From: JohnS on
Hi there,

I'm currently using the following pattern in various place but just realized
it's probably not safe. Can someone comment on this:

public DataRow GetWhatever()
{
using (DataTable dataTable = GetDataTable())
{
return dataTable[0];
}
}

The problem is that "DataRow" has a "Table" property that points back to the
same "dataTable" in the "using" statement above. That object is disposed of
in the "using" statement however so I assume the "Table" property will now
point to garbage (or rather an object that shouldn't be used anymore). Is
this correct? Note BTW that the indexer above is actually present in my case
(the "DataTable" is actually a "DataTable" derivative created using the VS
dataset designer)

From: Peter Duniho on
JohnS wrote:
> Hi there,
>
> I'm currently using the following pattern in various place but just
> realized it's probably not safe. Can someone comment on this:
>
> public DataRow GetWhatever()
> {
> using (DataTable dataTable = GetDataTable())
> {
> return dataTable[0];
> }
> }
>
> The problem is that "DataRow" has a "Table" property that points back to
> the same "dataTable" in the "using" statement above. That object is
> disposed of in the "using" statement however so I assume the "Table"
> property will now point to garbage (or rather an object that shouldn't
> be used anymore). Is this correct? Note BTW that the indexer above is
> actually present in my case (the "DataTable" is actually a "DataTable"
> derivative created using the VS dataset designer)

Yes, you definitely don't want to dispose objects that are being
returned for use by the caller.

The "using" statement is great for situations where you create an object
that is to be used locally, and for which its lifetime should not extend
beyond the method call in which the "using" statement is found. But
it's not a panacea. If your disposable object needs to live longer than
the method in which it's been created, you need to manage the lifetime
of the object more explicitly, by setting up some guidelines with
respect to ownership of the object and ensuring that the code that winds
up with ownership of the object does the necessary call to Dispose()
when it's actually done with it.

Pete
From: Mr. Arnold on
JohnS wrote:
> Hi there,
>
> I'm currently using the following pattern in various place but just
> realized it's probably not safe. Can someone comment on this:
>
> public DataRow GetWhatever()
> {
> using (DataTable dataTable = GetDataTable())
> {
> return dataTable[0];
> }
> }
>
> The problem is that "DataRow" has a "Table" property that points back to
> the same "dataTable" in the "using" statement above. That object is
> disposed of in the "using" statement however so I assume the "Table"
> property will now point to garbage (or rather an object that shouldn't
> be used anymore). Is this correct? Note BTW that the indexer above is
> actually present in my case (the "DataTable" is actually a "DataTable"
> derivative created using the VS dataset designer)

The real problem is you did a return in the middle of the using
statement, so the using statement has been short circuited.

The return should be after the using statement.

It should be like this.

public DataRow GetWhatever()
{
var dr = new DataRow();

using (DataTable dataTable = GetDataTable())
{
dr = dataTable[0];
}

return dr;
}
From: JohnS on
> Yes, you definitely don't want to dispose objects that are being returned
> for use by the caller.
>
> The "using" statement is great for situations where you create an object
> that is to be used locally, and for which its lifetime should not extend
> beyond the method call in which the "using" statement is found. But it's
> not a panacea. If your disposable object needs to live longer than the
> method in which it's been created, you need to manage the lifetime of the
> object more explicitly, by setting up some guidelines with respect to
> ownership of the object and ensuring that the code that winds up with
> ownership of the object does the necessary call to Dispose() when it's
> actually done with it.

Thanks for the feedback. I think that (unmanaged) resource management in
..NET is a potential trip wire in cases like this. It can certainly be
difficult to manage anyway. I simply want to return a "DataRow" in this case
but now what. Clients should explicitly call "dataRow.Table.Dispose()"? From
what I understand, you don't even need to worry about disposing ADO.NET
objects like "DataTable" in current releases but it inherits from
"IDisposable" so in theory it should be disposed of (AFAIK). I'm not going
to worry about it however. I'm going to remove those "using" statements and
let the GC clean things up (for ADO.NET objects anyway). Thanks again for
your help.

From: Peter Duniho on
JohnS wrote:
> Thanks for the feedback. I think that (unmanaged) resource management in
> ..NET is a potential trip wire in cases like this. It can certainly be
> difficult to manage anyway. I simply want to return a "DataRow" in this
> case but now what. Clients should explicitly call
> "dataRow.Table.Dispose()"? From what I understand, you don't even need
> to worry about disposing ADO.NET objects like "DataTable" in current
> releases but it inherits from "IDisposable" so in theory it should be
> disposed of (AFAIK). I'm not going to worry about it however. I'm going
> to remove those "using" statements and let the GC clean things up (for
> ADO.NET objects anyway). Thanks again for your help.

If the object implements IDisposable, you should write the code to
handle disposing. Period. To do otherwise makes one of two statements:

� I will never ever change this code or the exact platform
implementation on which it runs. It's frozen in time.

� I don't care about resource management.

Hopefully the second is not a true statement, and it's very rare that
the first is ever true.

Dealing with IDisposable objects is definitely more difficult than
managed objects. It's an unfortunate consequence of having .NET
leverage the existing OS implementation, rather than being a completely
new platform unto itself. But, that doesn't make this "trip wire"
(which implies some kind of booby trap).

It's just something you need to understand. It's no worse than needing
to understand: performance characteristics of a garbage-collected
system; the need to unsubscribe your methods from event handlers to
ensure your class will be collected; etc.

As for the specific example, again� the correct solution depends on the
lifetime of the object. If the lifetime of the object need not extend
beyond the lifetime of the caller, then the caller can simply use a
"using" statement to manage that:

public void DoWhicever()
{
using (DataRow row = GetWhatever())
{
// do stuff
}
}

If the lifetime extends beyond the lifetime of any given method, then
you'll need some other mechanism. This is often as simple as the
disposable object being contained within some other disposable object,
the lifetime of which is already being managed correctly, and disposing
the first object when the containing object is disposed.

What you can't do and expect to have a useful, maintainable, correct
program is to just ignore the situation.

Pete