1

I have read the MSDN page on this: https://msdn.microsoft.com/en-us/library/ms182334.aspx

And also this SO answer: https://stackoverflow.com/a/32554589/2257227

But the following code still generates 2 CA2202 warnings for me:

FileStream fileStream = null;
BufferedStream bufferedStream = null;
try
{
    fileStream = File.Open(...);
    bufferedStream = new BufferedStream(fileStream);

    using (StreamReader streamReader = new StreamReader(bufferedStream))
    {
        ...
    }
}
finally
{
    if (bufferedStream != null)
    {
        bufferedStream.Dispose();
    }

    if (fileStream != null)
    {
        fileStream.Dispose();
    }
}

The "bufferedStream.Dispose()" line still gives the following two warnings:

Severity Code Description Project File Line Suppression State Warning CA2202 Object 'bufferedStream' can be disposed more than once in method 'Loader.UpdateIndex()'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 930 Loader C:\Users\user\Loader\Loader.cs 930 Active

and

Severity Code Description Project File Line Suppression State Warning CA2202 Object 'fileStream' can be disposed more than once in method 'Loader.UpdateIndex()'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 930, 935 Loader C:\Users\user\Loader\Loader.cs 930 Active

Presumably this is because fileStream could be disposed of more than once? But how can bufferedStream be disposed of more than once?

Edit: I've marked @Damien_The_Unbeliever's answer as correct. You can actually trim it down as well, because as was mentioned somewhere below, you don't need the bufferedReader variable. Here's what I ended up with. It's kinda ugly, but it works:

FileStream fileStream = null;
try
{
    fileStream = File.Open("iaushdiuh", FileMode.Open);

    fileStream = null;

    using (StreamReader streamReader = new StreamReader(fileStream))
    {
        streamReader.ReadLine();
    }
}
finally
{
    if (fileStream != null)
    {
        fileStream.Dispose();
    }
}
Community
  • 1
  • 1
John Darvill
  • 1,274
  • 11
  • 17
  • Do you *use* either `fileStream` or `bufferedStream` after you've passed them to other constructors? – Damien_The_Unbeliever Apr 21 '17 at 10:44
  • I find your edit disingenuous. The code I've placed in my answer compiles (with build analysis turned on) with zero warnings (provided the `...` chunks are replaced with usable code), under VS 2017. If you have a *reproducible* code sample that can provoke warnings, please [edit] your question to include it. – Damien_The_Unbeliever Apr 21 '17 at 17:04
  • @Damien_The_Unbeliever Hey, sorry I didn't have time to look into this anymore at the time, but I've just come back to it and yes, your solution doesn't generate any warnings, thanks. I've marked the answer as correct and will edit my original post. – John Darvill May 05 '17 at 10:49

1 Answers1

2

If you don't use the underlying streams after you've "passed ownership" of these objects to other objects, you can silence the warning like this:

        FileStream fileStream = null;
        BufferedStream bufferedStream = null;
        try
        {
            fileStream = File.Open(...);
            bufferedStream = new BufferedStream(fileStream);

            fileStream = null;

            using (StreamReader streamReader = new StreamReader(bufferedStream))
            {

                bufferedStream = null;

                ...
            }
        }
        finally
        {
            if (bufferedStream != null)
            {
                bufferedStream.Dispose();
            }

            if (fileStream != null)
            {
                fileStream.Dispose();
            }
        }

You'll want the assignments to null to occur immediately following the constructor call that "takes ownership" of the disposable object. In this way, you ensure that if the constructor throws, you dispose the inner object and if the constructor succeeds then it is then going to arrange for disposal to occur.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
  • doing this, `finally` can be removed and the following can be added at the end of the using() `fileStream = null;` `bufferedStream = null;` – Donald Jansen Apr 21 '17 at 10:51
  • @DonaldJansen - no, you'll still get a warning doing that. The point is to `null` out the appropriate variable as soon as another constructor has completed without throwing an exception and so that newly constructed object is now responsible for disposal. – Damien_The_Unbeliever Apr 21 '17 at 10:54
  • Thanks for the reply, but I still get a 2202 warning using this method. – John Darvill Apr 21 '17 at 12:11
  • @JD41 - I get no warnings on this code exactly as listed, provided I replace the first `...` with valid parameters and replace the second `...` with just some other code. – Damien_The_Unbeliever Apr 21 '17 at 12:13