开发者

Returning instance created in 'using' statement

If I have this method:

开发者_如何学编程
public StreamReader GetResourceStream(string filename)
{
    using (Stream stream = this.GetType().Assembly.GetManifestResourceStream(filename))
    using (StreamReader sr = new StreamReader(stream))
    {
        return sr;
    }
}

When I call it, should I call it this way

StreamReader resource = GetResourceStream("blah.xml");

or this way:

using (StreamReader resource = GetResourceStream("blah.xml"))
{
    // Do stuff
}

If second way, does this means the using (StreamReader sr = new StreamReader(stream)) line is not making any difference by using a using statement?


You should change the method itself not to include a using statement, but then make sure that the calling code uses a using statement:

public StreamReader GetResourceStream(string filename)
{
    return new StreamReader(GetType().Assembly
                                     .GetManifestResourceStream(filename));
}

using (StreamReader resource = GetResourceStream("blah.xml"))
{
    // Do stuff
}

That way it will only dispose of the resource when you've actually used it. Basically the method is giving ownership of the returned resource to the caller. That much isn't too bad - it's reasonably common, even (think of File.OpenText etc).

Where it gets more tricky is when you pass a resource into a method or constructor - should the "called" code take ownership or not? Usually not, but occasionally it's appropriate - for example, the Bitmap(Stream) documentation states that you must keep the stream alive for as long as the bitmap is required. In fact, disposing of the bitmap also disposes of the stream, so you still only have one resource to keep track of... but you do need to know that you mustn't close the stream.


It doesn't really make sense to have the GetResourceStream method put the using statement around the object it's returning. That means you will be returning an object in a disposed state, and what good is that? It will throw ObjectDisposed exceptions at you.

So remove the using statements inside your factory method, and apply the using statement where you're actually using it.

It should look more like this:

public StreamReader GetResourceStream(string filename)
{
    Stream stream = this.GetType().Assembly.GetManifestResourceStream(filename);
    return new StreamReader(stream)        
}


When program flow exits the second using block, sr.Dispose() will be called, disposing the StreamReader and making it useless.

You need to make use of sr before flow control exits that block.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜