CA2000 and CA2202 warnings have recently been the bane of my existence. What am I doing wrong here? I basically get a FileStream
using File.Open
and then pass it into a function that may return a new stream or may return the same stream. I then perform some more actions on my stream and then in my finally
block I dispose the stream I was using if it was different.
I get two CA warnings. 2000 for fileStream
in the using
block and 2202 for changedStream
in the finally
block. What gives?
using (Stream fileStream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
Stream changedStream = null;
try
{
changedStream = someCondition ? fileStream : DoSomeActionThatMayReturnNewStream(fileStream);
DoSomeMoreStuffWithStream(changedStream);
}
finally
{
if (changedStream != null && changedStream != fileStream)
{
changedStream.Dispose();
}
}
}
Under what cases, if any, will
DoSomeActionThatMayReturnNewStream
dispose of the passed-in stream? If when it creates a new stream it disposes of the passed-in one (which would generally be expected), theDispose
triggered by theusing
block will be redundant.It appears as though the behavior of your code might be correct if
DoSomeActionThatMayReturnNewStream
never disposes of the passed-in stream, but FxCop has no way of analyzing its complex and unorthodox pattern of object ownership. I would suggest that it would be better to do something likeThe
DoSomeActionThatMayReturnNewStream
should dispose of the old stream if it's going to open a new one. It should null the variable immediately before closing the old stream and and assign it immediately upon opening the new one. That will ensure that if an exception occurs during the method, the old stream will get disposed if and only if it hasn't been disposed before, and the new stream will get disposed if its constructor completed, even if theDoSomeActionThatMayReturnNewStream
threw an exception after that [if that method callsDispose
on the new stream in case an exception gets thrown, it should null out the variable in such case].