Behaviour of streams in and out of scope

G

Guest

Hi...

I was wondering what happens to streams when they're passed between objects,
because my understanding of them is that they're effectively a pointer to a
data structure (or a location within it), rather than a copy of the structure
itself. E.g. a file stream is not a copy of the file (as a string would be,
for example, if you read it all into a string) but a means of accessing the
file. So that got me thinking about the scope behaviour of the stream.

Sample code may make it easier to see what I mean:

namespace Streams_in_scope
{
class Program
{
static void Main(string[] args)
{
// instantiated object, with local instance variable returned as
stream. You'd think this would work.
LocalScope testClass = new LocalScope();
Stream foo = testClass.foo;

// static class, with method which returns stream. How this will
work I don't know - there's no actual instance of the object, so the stream
has nowhere to "come from" if it isn't fully populated and returned as a
whole collection of bytes.
Stream bar = StaticLocalScope.GetFoo();

// class with an external source of data, returned as a stream.
// Is it a pointer to the file? Or as a pointer to a file
reference contained within the class which goes out of scope?
// will the stream cease to exist when leaving scope, when GC
runs, or never?
Stream foobar;
try
{
foobar = ExternalFileStream.GetFoobar();
}
catch
{ }

}
}

class LocalScope
{
private string _foo = "and now is the time for all good men to come
to the aid of the party.";
public Stream foo
{
get
{
Stream fooStream = new MemoryStream();
StreamWriter sw = new StreamWriter(fooStream);
sw.Write(_foo);
return fooStream;
}
}
}

static class StaticLocalScope
{
public static Stream GetFoo()
{
string _foo = "and now is the time for all good men to come to
the aid of the party.";
Stream fooStream = new MemoryStream();
StreamWriter sw = new StreamWriter(fooStream);
sw.Write(_foo);
return fooStream;
}
}

static class ExternalFileStream
{
public static Stream GetFoobar()
{
Stream fs =
File.OpenRead(@"c:\windows\system32\drivers\etc\hosts");
return fs;
}
}
}


There I have a few methods, each of which returns a stream. The first I
would expect to work "properly" - in that the object which contains the data
the stream points to continues to exist. Thus, the stream should keep working.

The second, I'm not sure of. How does reference counting work on a static
class, which is therefore not instantiated and so can have no references to
an instance? Will the stream work? Won't it? Will garbage collection come
along and remove the underlying data but leave me with a Stream pointing to
either null, or some random block of RAM?

The third, I'm even less sure of. It's a static class, which also goes out
of scope at the end of the try block. It should DEFINITELY be collectable.
Will my returned FileStream be a stream on the file (in which case it should
work independent of GC activity), or on a representation of that file (a
filehandle, if you like) in the scope of my ExternalFileStream class (in
which case, the filehandle could reasonably be collected by GC and I'm left
again with a FileStream to a filehandle which doesn't exist.

Anyone know the answer?

Kev
 
M

Mattias Sjögren

Kevin,
I was wondering what happens to streams when they're passed between objects,
because my understanding of them is that they're effectively a pointer to a
data structure (or a location within it), rather than a copy of the structure
itself.

That's true for any reference type, including Streams.

E.g. a file stream is not a copy of the file (as a string would be,
for example, if you read it all into a string) but a means of accessing the
file.

A string is also a reference type.

The second, I'm not sure of. How does reference counting work on a static
class, which is therefore not instantiated and so can have no references to
an instance?

It doesn't matter where you instantiate the stream. The fact that it
comes from a method in a static class is totally irrelevant (so all
three of your code snippets will work fine). The only thing that
matters is that you keep a reference to the stream object itself. As
long as you do, the object will be valid and not collected by GC.

Will garbage collection come
along and remove the underlying data but leave me with a Stream pointing to
either null, or some random block of RAM?

No, that never happens. GC only cleans up objects that aren't
referenced anymore (or only referenced by other objects eligible for
collection). GC will not null out references or make them invalid.

The third, I'm even less sure of. It's a static class, which also goes out
of scope at the end of the try block. It should DEFINITELY be collectable.

Since there's no instance of the static class, there's nothing to
collect. And scope has nothing to do with it.


In summary, you worry too much :)


Mattias
 

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

Top