2016-05-26 15 views
0

Когда я выбираю Analyze> RUn Code Analysis для решения в Visual Studio 2013, я получаю: «CA2202 Не располагайте объекты несколько раз. Объект« fs »может быть удален более чем один раз в методе« RoboReporterSQL.SaveReportDataToDB (строка, строка) .. Чтобы избежать генерации System.ObjectDisposedException не следует вызывать Dispose больше, чем один раз на объекте "Должен ли я прислушаться к этому поверхностно бессмысленному предупреждению анализа кода?

указанная строка кода:

fs.Close(); 

А вот код в контексте:

internal static void SaveReportDataToDB(string filename, string 
RESTFilename) 
    { 
     if (RecordAlreadyExists(RESTFilename)) return; 
     string EXCEL_FILE = "application/vnd.ms-excel"; 
     DateTime begDate = 
RoboReporterConstsAndUtils.GetBeginDate(RESTFilename); 
     DateTime endDate = 
RoboReporterConstsAndUtils.GetEndDate(RESTFilename); 

     var fs = new FileStream(filename, FileMode.Open, FileAccess.Read); 
     BinaryReader br = new BinaryReader(fs); 
     Byte[] bytes = br.ReadBytes((Int32)fs.Length); 
     br.Close(); 
     fs.Close(); 

     using (var sqlConn = new SqlConnection(CPSConnStr)) 
     { 
      var insertStr = "INSERT INTO ReportsGenerated (FileBaseName, 
ContentType, BinaryData, BeginDate, EndDate) " + 
          "VALUES (@FileBaseName, @ContentType, 
@BinaryData, @BeginDate, @EndDate)"; 

      using (var insertRptsGenerated = new SqlCommand(insertStr)) 
      { 
       insertRptsGenerated.Connection = sqlConn; 
       insertRptsGenerated.Parameters.Add("@FileBaseName", 
SqlDbType.VarChar, 100).Value = RESTFilename; 
       insertRptsGenerated.Parameters.Add("@ContentType", 
SqlDbType.VarChar, 50).Value = EXCEL_FILE; 
       insertRptsGenerated.Parameters.Add("@BinaryData", 
SqlDbType.Binary).Value = bytes; 
       insertRptsGenerated.Parameters.Add("@BeginDate", 
SqlDbType.DateTime).Value = begDate; 
       insertRptsGenerated.Parameters.Add("@EndDate", 
SqlDbType.DateTime).Value = endDate; 
       sqlConn.Open(); 
       insertRptsGenerated.ExecuteNonQuery(); 
      } 
     } 
    } 

Таким образом, предупреждение утверждает, что FileStream закрывается дважды, если я вызываю «fs.Close();»

Хотя я не опровергаю это с уверенностью, я сомневаюсь в этом, потому что я не вижу, чтобы он был закрыт.

В конце концов, он не находится в «используемом» блоке, так как он закрывается?

Вопрос: должен ли я действительно удалить эту строку кода ("fs.Close();")?

Примечание: решар не проклинал [g] e whit about this - с помощью «fs.Close();» в или из, он не поднимает никаких предупреждающих знаков в любом случае.

+2

Вы закрываете его дважды. Вы закрываете его при закрытии BinaryReader - он также закрывает базовый поток. И вы действительно должны использовать –

+2

. Это обсуждается с смертью на SO, и только ваша репутация сохраняет вопрос ... –

+0

Мне интересно, если формулировка ошибки в этом случае. Если закрытие «BinaryReader» может привести к удалению «FileStream», доступ к методу «Закрыть» объекта, который может быть удален, может вызвать «ObjectDisposedException». –

ответ

4

Откровенно говоря, вы не должны закрывать эти потоки явно, вы должны использовать блоки using.

В любом случае, это дает вам предупреждение, потому что поток уже закрыт. Когда читатели/писатели обертывают поток, закрытие их также закрывает основной поток. Некоторые из читателей/писателей дают вам возможность оставить поток открытым.

В вашем конкретном случае вы можете убить двух зайцев одним выстрелом, используя некоторые другие методы, доступные в классе File. Рассмотрите возможность использования File.ReadAllBytes() для чтения в вашем файле.

3

Хотите добавить, что это все еще совершенно бесполезное предупреждение. Я никогда не видел реализации IDisposable, которая бы бросила ObjectDisposedException, когда вы вызываете Dispose несколько раз. На самом деле в документации IDisposable.Dispose следующий написано:

Если метод Dispose объекта вызывается более чем один раз, то объект должен игнорировать все вызовы после первого. Объект не должен бросить исключение, если его Dispose метод вызывается несколько раз

Однако вы звоните Close на вашем потоке, не Dispose, и в то время как в данном случае это то же самое, в общем, вы действительно не должны называть любой non-Dispose на расположенных объектах, поэтому по крайней мере измените Close to Dispose (или лучше оберните все в использовании).

+0

Интересно, может ли это быть так, потому что «BinaryReader» был закрыт, что «FileStream» может быть удален. Поэтому предупреждение говорит о том, что доступ к уже удаленному объекту FileStream (fs) может привести к «ObjectDisposedMethod». Я имею в виду, что произойдет, если вы выберете «FileStream», а затем вызовите метод «Закрыть»? –

+0

Ничего не происходит. Но если вы попытаетесь сделать что-нибудь еще (чтение \ запись и т. Д.), То это вызовет ObjectDisposedException. Я использую этот шаблон (избавляющий читателя и поток в двух блоках) уже много лет, без каких-либо проблем. – Evk

+0

Я не имею в виду утилизацию дважды. Я имею в виду, что доступ к методу «Закрыть» уже расположенного объекта может бросить, не так ли? –

 Смежные вопросы

  • Нет связанных вопросов^_^