How to return a Stream from a method, knowing it should be disposed?

后端 未结 3 1029
囚心锁ツ
囚心锁ツ 2021-01-01 10:55

I have a method that takes FileStream as input. This method is running inside a for loop.

private void UploadFile(FileStream fileStream)
{
    var stream = G         


        
3条回答
  •  生来不讨喜
    2021-01-01 11:27

    The problem is that the FileStream object is disposed as soon as you exit from the GetFileStream() method, leaving it in an unusable state. As other answers already indicate, you need to remove the using block from that method and instead put the using block around any code that calls this method:

    private FileStream GetFileStream()
    {
        FileStream fileStream = File.Open(myFile, FileMode.Open);
        //Do something
        return fileStream;
    }
    
    using (var stream = GetFileStream())
    {
        UploadFile(stream);
    }
    

    However, I want to take this a step further. You want a way to protect the stream created by your GetFileStream() from the case where a sloppy programmer might call the method without a using block, or at least somehow strongly indicate to callers that the result of this method needs to be enclosed with a using block. Therefore, I recommend this:

    public class FileIO : IDisposable
    {
        private FileStream streamResult = null;
    
        public FileStream CreateFileStream(string myFile)
        {
            streamResult = File.Open(myFile, FileMode.Open);
            //Do something
            return streamResult;
        }
    
        public void Dispose()
        { 
           if (streamResult != null) streamResult.Dispose();         
        }
    
    }
    
    using (var io = FileIO())
    {
        var stream = io.CreateFileStream(myFile);
    
        // loop goes here.
    }
    

    Note that you don't necessarily need to create a whole new class for this. You may already have an appropriate class for this method where you can just add the IDisposable code. The main thing is that you can use IDisposable as a signal to other programmers that this code should be wrapped with a using block.

    Additionally, this sets you up to modify the class so that you could create your IDisposable object once, before the loop, and have the new class instance keep track of everything you need to dispose at the end of the loop.

提交回复
热议问题