這個n到底是多少年?宇宙第一開發IDE Visual Studio的調試功能非常強大,平常工作debug幫助我們解決不少問題。今天分享兩個異常捕獲的技巧,希望能夠幫助解決一些問題。
以下兩種情況,我相信大家都會遇到過。
1.沒有使用Try-Catch語句,當異常發生的時候,能夠自動跳轉到異常發生的地方,在使用Try-Catch捕獲異常的時候,直接跳轉到Catch語句的位置,并不會自動定位到異常代碼的位置。
2.使用Try-Catch的時候,多層方法調用時,并不能直接檢視到異常代碼的位置。
技巧1:自動定位到異常代碼位置
針對問題1,我們最想要的結果是,哪裡有代碼出現錯誤了,就直接定位到哪兒,異常出在哪行代碼上,我一眼就能看得出,這樣就能更快地處理問題了。
對于問題1,所出現的這種情況,簡單複現一下一個空引用的異常
namespace ExceptionSample
{
class Program
{
static void Main(string[] args)
{
try
{
Random random = null;
Console.WriteLine(random.Next());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadLine();
}
}
}
上面的異常代碼NullReferrenceException,Debug模式下,會跳轉到catch語句這裡。你可能覺得這挺簡單的…可實際實際工作中,你的一個方法中僅僅隻這一個對象嗎?

在實際工作中可能不止random一個對象,代碼複雜,對象夠多,幾十個也有,我們就很難定位到異常出錯的代碼了。StackTrace可以定位到那個函數調用錯了,并不能定位到哪一行代碼出錯了。
為了解決這個行為可以通過在Visual Studio中菜單欄中的調試》視窗》異常設定中去配置。如下圖所示:
勾選上Common Language Runtime Exceptions下列的異常單選框。有點多,以前的設定有些變化。
現在我們再看之前的代碼,使用Try-Catch語句捕獲異常的時候,就會直接定位到異常代碼的位置了,如下圖示:
static void Main(string[] args)
{
try
{
Random random = null;
Random random1 = new Random();
Random random2 = new Random();
Random random3 = new Random();
Console.WriteLine(random1.Next());
Console.WriteLine(random2.Next());
Console.WriteLine(random3.Next());
Console.WriteLine(random.Next());
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadLine();
}
技巧2:正常的throw 姿勢
還是之前的一個方法,我已經将異常設定回複預設了。
static void Main(string[] args)
{
try
{
Random random = null;
Console.WriteLine(random.Next());
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex);
throw ex;
}
}
我們再輸出中可以看到(ps:項目名稱用的之前的,不介意哈)
錯誤的代碼在16行。可實際工作中的情況并不是這樣簡單,基本上是A方法調用B方法,B方法調用C方法,代碼如下所示:
在Main方法中調用ThrowNullReferrence(),方法ThrowNullReferrence中調用SetNullReferrence()。代碼變複雜後,一層嵌套一層。這個時候能正确顯示出代碼異常的位置嗎?
static void Main(string[] args)
{
try
{
ThrowNullReferrence();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex);
throw ex;
}
}
public static void ThrowNullReferrence()
{
try
{
SetNullReferrence();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex);
throw ex;
}
}
public static void SetNullReferrence()
{
try {
Random random = null;
Console.WriteLine(random.Next());
}
catch(Exception ex)
{
System.Diagnostics.Debug.Write(ex);
throw ex;
}
}
我們可以通過下圖看到:
System.NullReferenceException: 未将對象引用設定到對象的執行個體。
在 ExceptionSample.Program.SetNullReferrence() 位置 D:Learn延遲加載LinqLayzLoadLinqLayzLoadProgram.cs:行号 39System.NullReferenceException: 未将對象引用設定到對象的執行個體。
在 ExceptionSample.Program.SetNullReferrence() 位置 D:Learn延遲加載LinqLayzLoadLinqLayzLoadProgram.cs:行号 44
在 ExceptionSample.Program.ThrowNullReferrence() 位置 D:Learn延遲加載LinqLayzLoadLinqLayzLoadProgram.cs:行号 27System.NullReferenceException: 未将對象引用設定到對象的執行個體。
在 ExceptionSample.Program.ThrowNullReferrence() 位置 D:Learn延遲加載LinqLayzLoadLinqLayzLoadProgram.cs:行号 32
在 ExceptionSample.Program.Main(String[] args) 位置 D:Learn延遲加載LinqLayzLoadLinqLayzLoadProgram.cs:行号 15
錯誤代碼的位置在39行,以上出現異常的地方都是throw的位置。
原因呢?
catch捕獲完後,如果要向上抛出,應該重新執行個體化一個新的異常對象,再向上抛出,這個最外層方法catch到的才是完整的異常,當然也包括完整的堆棧資訊,這樣才能定位到異常代碼的位置。
要使用 throw new Exception
改造後的例子如圖,精準定位到
39行的空引用異常
Console.WriteLine(random.Next());
結語
分享之前看到的一個老程式員的經驗之談:“多coding,少debug”,
回到标題為什麼說"使用Vistual Studio n年",這個n到底指的是多少年。我的意思是可能有些東西,即使使用多年,可能不知道這兩個技巧。
文章來源:
https://blog.csdn.net/kebi007/article/details/103439933更多技術内容:
https://www.roncoo.com