Почему анализ кода говорит мне:" не размещайте объекты несколько раз " здесь:
По этому коду:
public static string Base64FromFileName(string fileName)
{
try
{
FileInfo fInfo = new FileInfo(fileName);
long numBytes = fInfo.Length;
FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fStream);
byte[] bdata = br.ReadBytes((int)numBytes);
br.Close();
fStream.Close();
return Convert.ToBase64String(bdata);
}
catch(Exception e)
{
throw e;
}
}
...Я получаю, благодаря инструменту анализа кода Visual Studio, предупреждение: "Не размещайте объекты многократно times...To избегайте создания системы.ObjectDisposedException не следует вызывать Dispose более одного раза для объекта " на " fStream.Замкнутая линия.
Почему? Расположен ли fStream в строке выше, где BinaryReader закрыт?
Не лучше ли мне все равно рефакторинговать его так:
. . .
using (FileStream fStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fStream))
{
byte[] bdata = br.ReadBytes((int)numBytes);
} //br.Close();
} //fStream.Close();
. . .
?
2 ответа:
BinaryReader.CloseКроме того, закрывает основной поток, так что это действительно приведет к тому, что поток будет удален дважды. Но это не настоящая проблема, избавиться дважды не повредит.Вы могли бы написать это гораздо лучше, как
using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) using (var br = new BinaryReader(fs, new UTF8Encoding(), true)) { return Convert.ToBase64String(br.ReadBytes((int)numBytes)); }Это бомбоубежищная версия:
- Все, что успешно построено, гарантированно будет утилизировано
- вы не будете избавляться от потока дважды, потому что логический аргумент
leaveOpenв конструктореBinaryReaderгарантирует, что утилизации (закрытии) его не закрыть поток
Анализ кода-это правильно; анализ кода-это неправильно.
Да, вы закрываете поток файлов дважды. Это безобидно. Так же как и избавление от него дважды. Происходит многократная утилизация. Ответственность разработчика одноразового компонента заключается в том, чтобы правильно и без исключений обрабатывать многократную утилизацию.1.
Однако, в то время как вызов
Dispose()на disposedFileStreamявляется no-op по соглашению, то же самое не верно для вашего кода, который вызываетClose()на disposed stream. Не делай этого.Предложенное вами исправление с вложенным использованием прекрасно.
1контракт для
IDisposable.Disposeтребуется:Если метод объекта
Disposeвызывается более одного раза, объект должен игнорировать все вызовы после первого. Объект не должен вызывать исключение, если его методDisposeвызывается несколько раз. Методы экземпляра, отличные отDispose, могут выбрасыватьObjectDisposedException, когда ресурсы уже расположены.Формальный термин для этого поведение idempotence.