How can I find if a TextWriter / StreamWriter is disposed?

  • Thread starter Thread starter Zytan
  • Start date Start date
Zytan said:
That's my thought. Perhaps I am just not comfortable with exceptions,
since they are for exceptional behaviour. But, maybe this is such a
thing.
This surely is an exeptional behaviour. First, your logger class shouldn't
be called from a finalizer (though some might think it's usefull to do).
Second, the run of a finalizer itself should be exceptional. An application
running hundreds of finalizers per second surely has some bug and is in a
very very exceptional case.

If you still want to avoid this exception, you could use an instance
variable, wich marks, if the stream is open. I don't know, where you get the
stream from, but I think your logger class is the only class, wich can
dispose it.

Christof
 
If you still want to avoid this exception, you could use an instance
variable, wich marks, if the stream is open. I don't know, where you get
the stream from, but I think your logger class is the only class, wich can
dispose it.

Hi Zytan,

reading one of your other posts, I noticed that this surely can fail. Your
right, the stream can be disposed by it's own finalizer. But then your
logger class has also to be in the finalizer qeue (if it has a finalizer
itself). This gives me another idea. Maybe there is a way to detect, if the
instance itself is pending for finalization. or only living because it's
referenced directly or indirectly by the finalizing qeue.

But still I suppose, the exception is best suited here.

Christof
 
reading one of your other posts, I noticed that this surely can fail. Your
right, the stream can be disposed by it's own finalizer. But then your
logger class has also to be in the finalizer qeue (if it has a finalizer
itself). This gives me another idea. Maybe there is a way to detect, if the
instance itself is pending for finalization. or only living because it's
referenced directly or indirectly by the finalizing qeue.

But still I suppose, the exception is best suited here.

Christof, thanks for your posts. I am not trying to avoid using the
exception handling at all costs, I just thought maybe there's a
Stream.IsDisposed method that I am missing, or something, so I want to
be sure I'm doing the right thing.

I think handling the exception is proper. And it's easy and basically
fool proof. All is well! :)

Zytan
 
This will throw a NullReferenceException when called on a disposed sw or
sr .

No it will not.

sw.Dispose();

does not by magic set sw to null.
What you actually want is this:

if(sw != null && sw.BaseStream != null)
// go ahead, the underlying resource is still accessible.
else
...

The sw != null test is rather meaningless in the context
of the subject.

I have some doubts whether sw.BaseStream != null is sufficient. It
is based on the assumption that Dispose actually sets BaseStream
to null. Current implementation does. But if a future implementation
just call Dispose and do not set it to null, then the code will break.
I think sw.BaseStream.CanWrite is a nice extra check to have.

Arne
 
Zytan said:
Given the above code or the exception, I take the exception any day.
At least I know for 100% certainty that it will work, and it doesn't
rely on me understanding or typing the code example correctly.

You could wrap it in a method.

But I would also use the exception !

Arne
 
Willy said:
Hmmm.... Didn't you notice that this was a reply to Arne, and that I was
correcting his sample?

Messing it up.

Arne
 
Well, the concept of exceptions is hardly new and was around well before the
framework. I am uneasy that I am using .NET exception handling in situations
where functionally similar Win32 code would never raise an exception to
begin with. I have written TCP/IP client/servers using asynchronous model
(WSAAsyncSelect) and any socket to 'bite the dust', would send a message to
the a window it registered with. I had applications running around the clock
for several month serving data over DSL connections without ever raising an
exception. The .NET version also runs around the clock, however I see from
my logs that exceptions occur once in a while, sometimes days apart,
sometimes several times a day. Keeps me wondering if Win32 Winsock model is
better.

Michael
 
Arne Vajhøj said:
No it will not.

Sure it will , try this...

.....
StreamReader sr = null;
using ( sr = new StreamReader("canread.cs"))
{
.....
} // sr Disposed here.
if(sr != null && sr.BaseStream.CanRead)
Console.WriteLine("Stream can still be read from");

It will throw...

Unhandled Exception: System.NullReferenceException: Object reference not set to
an instance of an object.

sw.Dispose();

does not by magic set sw to null.


The sw != null test is rather meaningless in the context
of the subject.

I have some doubts whether sw.BaseStream != null is sufficient. It
is based on the assumption that Dispose actually sets BaseStream
to null. Current implementation does. But if a future implementation
just call Dispose and do not set it to null, then the code will break.
I think sw.BaseStream.CanWrite is a nice extra check to have.

Note, that future implementations can hardly change this behavior (which I don't rely upon
anyway!), without introducing a breaking change, if you look at the current implementation
of the FCL, setting BaseStream to null is done especially to guard themselves against
further access of the underlying stream.

Anyway, currently, BaseStream is effectively set to null in the SW or SR's Dispose method ,
so, sw.BaseStream.CanWrite will throw a NullReferenceException after the sw is disposed, so
what's the deal, handle a NullReferenceException or an bjectDisposedException?
I prefer the latter, the first one is too confusing, you don't expect this, right?.
That's why I assume "A disposed object being a dead object", I won't use it any longer.

Willy.
 
On Apr 4, 10:08 am, "Willy Denoyette [MVP]"

Sure it will , try this...

....
StreamReader sr = null;
using ( sr = new StreamReader("canread.cs"))
{
....
} // sr Disposed here.
if(sr != null && sr.BaseStream.CanRead)
Console.WriteLine("Stream can still be read from");

It will throw...

Unhandled Exception: System.NullReferenceException: Object reference not set to
an instance of an object.

Yes, because the BaseStream is null, but *not* because sr is null. The
variable sr won't become null just because you called Dispose on the
object.

Arne's code tested for sw.BaseStream being null. Change your test code
above to the code that Arne originally posted and it won't throw a
NullReferenceException.

Now, your point that you *only* need to test for sw.BaseStream being
null is a valid one (if somewhat implementation-specific) but you
don't need to test for sw being null unless you've got some code which
changes the value of the variable.

Jon
 
Jon Skeet said:
On Apr 4, 10:08 am, "Willy Denoyette [MVP]"



Yes, because the BaseStream is null, but *not* because sr is null. The
variable sr won't become null just because you called Dispose on the
object.
Arne's code tested for sw.BaseStream being null. Change your test code
above to the code that Arne originally posted and it won't throw a
NullReferenceException.

Waw ... my bad, Jeez, I missed sw.BaseStream != null in Arnes's sample.
Note that the check for CanRead is redundant, if "sw.BaseStream != null" holds true it means
that the underlying stream isn't disposed of, so no further check is required.

Now, your point that you *only* need to test for sw.BaseStream being
null is a valid one (if somewhat implementation-specific) but you
don't need to test for sw being null unless you've got some code which
changes the value of the variable.

True, this is only a sanity check ;-)
Not that I'm ever going to use this.

Willy.
 
Willy Denoyette said:
Sure it will , try this...

....
StreamReader sr = null;
using ( sr = new StreamReader("canread.cs"))
{
....
} // sr Disposed here.
if(sr != null && sr.BaseStream.CanRead)
Console.WriteLine("Stream can still be read from");

It will throw...

Unhandled Exception: System.NullReferenceException: Object reference not set to
an instance of an object.


Sorry, but forget about this sample, I misread the code sample you posted.

Willy.
 
Willy said:
Sorry, but forget about this sample, I misread the code sample you posted.

No problem.

I have misread post myself many times.

Worst - when I was really criticizing what I though was
pseudo code for not being valid C - when some one pointed
out that it was in a PHP category ...

Arne
 

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