CA2000/CA2202 для Stream в операторе использования
Предупреждения CA2000 и CA2202 недавно были проклятием моего существования. Что я здесь не так делаю? Я в основном получаю FileStream
с помощью File.Open
а затем передать его в функцию, которая может вернуть новый поток или может вернуть тот же поток. Затем я выполняю еще несколько действий в моем потоке, а затем в моем finally
Блок Я распоряжаться потоком, который я использовал, если он был другим.
Я получил два предупреждения CA 2000 для fileStream
в using
блок и 2202 для changedStream
в finally
блок. Что дает?
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();
}
}
}
2 ответа
При каких случаях, если таковые имеются, будет DoSomeActionThatMayReturnNewStream
избавиться от переданного потока? Если, когда он создает новый поток, он избавляется от переданного (что обычно ожидается), Dispose
вызвано using
блок будет избыточным.
Кажется, что поведение вашего кода может быть правильным, если DoSomeActionThatMayReturnNewStream
никогда не избавляется от переданного потока, но FxCop не имеет возможности анализировать его сложную и неортодоксальную модель владения объектом. Я бы предположил, что было бы лучше сделать что-то вроде
Stream inputFile = null;
try
{
inputFile = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
DoSomeActionThatMayReturnNewStream(ref inputFile);
DoSomeMoreStuffWithStream(inputFile);
}
finally
{
if (inputFile != null)
inputFile.Dispose();
}
DoSomeActionThatMayReturnNewStream
должен избавиться от старого потока, если он собирается открыть новый. Она должна обнулять переменную непосредственно перед закрытием старого потока и назначать ее сразу после открытия нового. Это гарантирует, что если во время метода возникнет исключение, старый поток будет удален тогда и только тогда, когда он не был удален ранее, а новый поток будет удален, если его конструктор завершен, даже если DoSomeActionThatMayReturnNewStream
бросил исключение после этого [если этот метод вызывает Dispose
в новом потоке в случае возникновения исключения, в этом случае он должен обнулять переменную].
Что не так со следующим:
using (var fileStream = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
using (var changedStream = someCondition ? fileStream : DoSomeActionThatMayReturnNewStream(fileStream))
{
DoSomeMoreStuffWithStream(changedStream);
}
}