问题
When I select Analyze > RUn Code Analysis on Solution in Visual Studio 2013, I get, "CA2202 Do not dispose objects multiple times Object 'fs' can be disposed more than once in method 'RoboReporterSQL.SaveReportDataToDB(string, string)'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object."
The indicated line of code is:
fs.Close();
And here is the code in context:
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();
}
}
}
So the warning is claiming that the FileStream is being closed twice if I call "fs.Close();"
Although I don't refute that with certainty, I question it because I don't see it being elsewhere closed.
After all, it is not in a "using" block, so how is it being closed?
The question is: should I really remove that line of code ("fs.Close();")?
Note: Resharper did not whin[g]e a whit about this - with "fs.Close();" in or out, it raises no warning flags either way.
回答1:
Frankly you shouldn't be closing those streams explicitly, you should be using using
blocks.
Anyway, it gives you that warning because the stream is already closed. When readers/writers wrap a stream, closing them will close the underlying stream as well. Some of readers/writers give you the option to leave the stream open however.
In your particular case, you can kill two birds with one stone by using some of the other methods available in the File
class. Consider using File.ReadAllBytes()
to read in your file.
回答2:
Want to add that it's still quite useless warning. I never saw any implementation of IDisposable
which would throw ObjectDisposedException
when you call Dispose multiple times. Actually in documentation of IDisposable.Dispose
the following is written:
If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times
However, you call Close on your stream, not Dispose, and while in this case it's the same, in general you indeed should not call any non-Dispose methods on disposed objects, so at least change Close to Dispose (or better wrap all in using).
来源:https://stackoverflow.com/questions/37467900/should-i-heed-this-superficially-nonsensical-code-analysis-warning