明明同事用了using來確保區塊結束時會呼叫Dispose()作到自動釋放資源,但還是被源碼檢測工具fortify舉報。呼~~來解題。
如下,Developer都很乖有使用using定義物件範圍來讓using區塊結束時呼叫Dispose()作到自動釋放資源
using (FileStream fsInFile = new FileStream(@"C:\Test\file.txt", FileMode.Open, FileAccess.Read, FileShare.None))
{
using (StreamReader srInFile = new StreamReader(fsInFile, System.Text.Encoding.Default))
{
string strInfData;
while ((strInfData = srInFile.ReadLine()) != null)
{
throw new Exception("somebody else"); //故意直接跳出method
}
}
}
另外,微軟docs對於using陳述式的說明:
提供方便的語法,以確保正確使用 IDisposable 物件。
但被掃出Unreleased Resource: Streams
查了using在微軟docs的說明,有一行吸引了眼球,文件她說即使發生Exception,也可以確保會執行Dispose
The using
statement ensures that Dispose is called even if an exception occurs within the using
block.
看來是fortify誤判了。
修正方法
老招,繼續神鬼交鋒,那我們在出事前加上一行Dispose()
using (FileStream fsInFile = new FileStream(@"C:\Test\file.txt", FileMode.Open, FileAccess.Read, FileShare.None))
{
using (StreamReader srInFile = new StreamReader(fsInFile, System.Text.Encoding.Default))
{
string strInfData;
while ((strInfData = srInFile.ReadLine()) != null)
{
fsInFile.Dispose();
throw new Exception("somebody else");
}
}
}
重新掃描:
結案!
實驗解構函式發生Exception跳出using區塊時是否會執行
除了看微軟Docs文件,我們也科學的做實驗。
我們有一個球員class:Footballer,New一個馬競前鋒grizmann起來執行射門之後,我們故意進入Exception,看看解構函示是否會執行?
using System;
namespace ConsoleApp1
{
internal class Program
{
private static void Main(string[] args)
{
Console.WriteLine("程式開始");
Attack();
Console.WriteLine("程式結束");
}
private static void Attack()
{
using (Footballer griezmann = new Footballer())
{
try
{
griezmann.Shot();
throw new Exception("Error");
}
catch (Exception e)
{
Console.WriteLine(e);
return;
}
}
}
}
internal class Footballer : IDisposable
{
public Footballer()
{
Console.WriteLine("建構函式");
}
public void Shot()
{
Console.WriteLine("射門!!!");
}
public void Dispose()
{
Console.WriteLine("解構函式");
GC.SuppressFinalize(this);
}
}
}
有執行解構!資源會被釋放~
Semi Finals
期待的4強,就少了西班牙。
參考
微軟docs using陳述式
https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/using-statement