首頁 後端開發 C#.Net教程 分析.NET的例外處理

分析.NET的例外處理

Aug 16, 2017 pm 05:06 PM
.net 處理 例外

這篇文章主要介紹了關於.NET異常處理的思考總結,具有一定的參考價值,有興趣的小夥伴們可以參考一下。

年關將至,對於大部分程式設計師來說,馬上就可以閒下來一段時間了,然而在這個閒暇的時間裡,唯有爭論哪門語言更好可以消磨時光,估計最近會有很多關於java與.net的博文出現,我表示要作為一個吃瓜群眾,靜靜的看著大佬們發表心情。

以上的廢話說的夠多了,這裡就不再廢話了,還是切入正題吧。

在專案開發中,對於系統和程式碼的穩定性和容錯性都是有對應的要求。實際開發專案中的程式碼與範例程式碼的差別,更多的是在程式碼的運作的穩定性、容錯性、擴展性的比較。因為對於實作一個功能來說,實作功能的核心程式碼是一樣的,可能只是在寫法上優化而已,但是在實作某一個操作上所使用的類別來說,這一點是絕大多數時候是一樣的。這樣看來,我們在實際開發的過程中,需要考慮的問題比較多,已經不只限於某一具體的功能實現,更多的是程式碼的穩定性和擴展性考慮。

以上是在實際開發中需要面對的問題,筆者在最近的博文中,也在考慮這個異常到底需要怎麼去寫,以及異常到底需要怎麼去理解,希望對大家有一個幫助,也歡迎大家提出自己的想法和意見,分享自己的知識和見解。

一.DotNET異常的概述:

#談到異常,我們就需要知道什麼叫做異常,萬事萬物如果我們想去學習,就應該知道我們要學習的東西是什麼,這樣在心裡也好有一個大概的認知。異常是指成員沒有完成它的名稱宣稱可以完成的行動。在.NET中,建構器、取得和設定屬性、新增和刪除事件、呼叫運算子重載和呼叫轉換運算子等等都沒有辦法回傳錯誤碼,但是在這些建構中又需要回報錯誤,那就必須提供異常處理機制。

在異常的處理中,我們常用的三個區塊分別是:try區塊;catch區塊;finally區塊。這三個區塊可以一起使用,也可以不寫catch區塊使用,異常處理區塊可以巢狀使用,具體的方法在下面會介紹到。

在異常的處理機制中,一般有三種選擇:重新拋出相同的異常,向調用棧高一層的程式碼通知該異常的發生;拋出一個不同的異常,想調用棧高一層程式碼提供更豐富的例外資訊;讓執行緒從catch區塊的底部退出。  

有關異常的處理方式,有一些指導性的建議。

1.恰當的使用finally區塊:

finally區塊可以保證不管執行緒拋出什麼類型的例外都可以被執行,finall區塊一般用來做清理那些已經成功啟動的操作,然後再回傳呼叫者或finally區塊之後的程式碼。

2.異常捕捉需適當:

為什麼要適當的捕捉異常呢?如下程式碼,因為我們不能什麼異常都去捕捉,在捕獲異常後,我們需要去處理這些異常,如果我們將所有的異常都捕捉後,但是沒有預見會發生的異常,我們就沒有辦法去處理這些異常。

如果應用程式程式碼拋出一個異常,應用程式的另一端則可能預期要捕捉這個異常,因此不能寫成一個」大小通吃「的異常塊,應該允許該異常在呼叫堆疊中向上移動,讓應用程式程式碼針對性地處理這個異常。

在catch區塊中,可以使用System.Exception捕捉異常,但是最好在catch區塊末尾重新拋出異常。至於原因在後面會講解到。


   try
   {
    var hkml = GetRegistryKey(rootKey);
    var subkey = hkml.CreateSubKey(subKey);
    if (subkey != null && keyName != string.Empty)
     subkey.SetValue(keyName, keyValue, RegistryValueKind.String);
   }
   catch (Exception ex)
   {
    Log4Helper.Error("创建注册表错误" + ex);
    throw new Exception(ex.Message,ex);
   }
登入後複製

3.從異常中恢復:

我們在捕獲異常後,可以針對性的寫一些異常恢復的程式碼,可以讓程式繼續運作。在捕獲異常時,需要捕獲特定的異常,充分的掌握在什麼情況下會拋出異常,並知道從捕獲的異常類型派生出了那些類型。除非在catch區塊的末尾重新拋出異常,否則不要處理或捕獲System.Exception異常。

4.維持狀態:

一般情況下,我們完成一個操作或一個方法時,需要呼叫幾個方法組合完成,在執行的過程中會出現前面幾個方法完成,後面的方法發生異常。發生不可恢復的異常時回滾部分完成的操作,因為我們需要恢復訊息,所有我們在捕獲異常時,需要捕獲所有的異常信息。

5.隱藏實作細節來維持契約:

有時可能需要捕捉一個例外並重新拋出一個不同的例外,這樣可以維繫方法的契約,拋出的心異常類型地應該是一個具體的異常。看如下程式碼:


#
FileStream fs = null;
   try
   {
    fs = FileStream();
    
   }
   catch (FileNotFoundException e)
   {
          //抛出一个不同的异常,将异常信息包含在其中,并将原来的异常设置为内部异常
    throw new NameNotFoundException();
   }
   catch (IOException e)
   {
 
    //抛出一个不同的异常,将异常信息包含在其中,并将原来的异常设置为内部异常
    throw new NameNotFoundException(); 
   } 
   finally 
   {
    if (fs != null) 
    { 
    fs.close(); 
   } 
   }
登入後複製

以上的代码只是在说明一种处理方式。应该让抛出的所有异常都沿着方法的调用栈向上传递,而不是把他们”吞噬“了之后抛出一个新的异常。如果一个类型构造器抛出一个异常,而且该异常未在类型构造器方法中捕获,CLR就会在内部捕获该异常,并改为抛出一个新的TypeInitialztionException。

二.DotNET异常的常用处理机制:

在代码发生异常后,我们需要去处理这个异常,如果一个异常没有得到及时的处理,CLR会终止进程。在异常的处理中,我们可以在一个线程捕获异常,在另一个线程中重新抛出异常。异常抛出时,CLR会在调用栈中向上查找与抛出的异常类型匹配的catch块。如果没有任何catch块匹配抛出的异常类型,就发生一个未处理异常。CLR检测到进程中的任何线程有一个位处理异常,都会终止进程。

1.异常处理块:

(1).try块:包含代码通常需要执行一些通用的资源清理操作,或者需要从异常中恢复,或者两者都需要。try块还可以包含也许会抛出异常的代码。一个try块至少有一个关联的catch块或finall块。

(2).catch块:包含的是响应一个异常需要执行的代码。catch关键字后的圆括号中的表达式是捕获类型。捕获类型从System.Exception或者其派生类指定。CLR自上而下搜素一个匹配的catch块,所以应该教具体的异常放在顶部。一旦CLR找到一个具有匹配捕获类型的catch块,就会执行内层所有finally块中的代码,”内层finally“是指抛出异常的tey块开始,到匹配异常的catch块之间的所有finally块。

使用System.Exception捕捉异常后,可以采用在catch块的末尾重新抛出异常,因为如果我们在捕获Exception异常后,没有及时的处理或者终止程序,这一异常可能对程序造成很大的安全隐患,Exception类是所有异常的基类,可以捕获程序中所有的异常,如果出现较大的异常,我们没有及时的处理,造成的问题是巨大的。

(3).finally块:包含的代码是保证会执行的代码。finally块的所有代码执行完毕后,线程退出finally块,执行紧跟在finally块之后的语句。如果不存在finally块,线程将从最后一个catch块之后的语句开始执行。

备注:异常块可以组合和嵌套,对于三个异常块的样例,在这里就不做介绍,异常的嵌套可以防止在处理异常的时候再次出现未处理的异常,以上这些就不再赘述。

2.异常处理实例:

(1).异常处理扩展方法:


  /// <summary>
  /// 格式化异常消息
  /// </summary>
  /// <param name="e">异常对象</param>
  /// <param name="isHideStackTrace">是否隐藏异常规模信息</param>
  /// <returns>格式化后的异常信息字符串</returns>
  public static string FormatMessage(this Exception e, bool isHideStackTrace = false)
  {
   var sb = new StringBuilder();
   var count = 0;
   var appString = string.Empty;
   while (e != null)
   {
    if (count > 0)
    {
     appString += " ";
    }
    sb.AppendLine(string.Format("{0}异常消息:{1}", appString, e.Message));
    sb.AppendLine(string.Format("{0}异常类型:{1}", appString, e.GetType().FullName));
    sb.AppendLine(string.Format("{0}异常方法:{1}", appString, (e.TargetSite == null ? null : e.TargetSite.Name)));
    sb.AppendLine(string.Format("{0}异常源:{1}", appString, e.Source));
    if (!isHideStackTrace && e.StackTrace != null)
    {
     sb.AppendLine(string.Format("{0}异常堆栈:{1}", appString, e.StackTrace));
    }
    if (e.InnerException != null)
    {
     sb.AppendLine(string.Format("{0}内部异常:", appString));
     count++;
    }
    e = e.InnerException;
   }
   return sb.ToString();
  }
登入後複製

(2).验证异常:


  /// <summary>
  /// 检查字符串是空的或空的,并抛出一个异常
  /// </summary>
  /// <param name="val">值测试</param>
  /// <param name="paramName">参数检查名称</param>
  public static void CheckNullOrEmpty(string val, string paramName)
  {
   if (string.IsNullOrEmpty(val))
    throw new ArgumentNullException(paramName, "Value can&#39;t be null or empty");
  }

  /// <summary>
  /// 请检查参数不是空的或空的,并抛出异常
  /// </summary>
  /// <param name="param">检查值</param>
  /// <param name="paramName">参数名称</param>
  public static void CheckNullParam(string param, string paramName)
  {
   if (string.IsNullOrEmpty(param))
    throw new ArgumentNullException(paramName, paramName + " can&#39;t be neither null nor empty");
  }

  /// <summary>
  /// 检查参数不是无效,并抛出一个异常
  /// </summary>
  /// <param name="param">检查值</param>
  /// <param name="paramName">参数名称</param>
  public static void CheckNullParam(object param, string paramName)
  {
   if (param == null)
    throw new ArgumentNullException(paramName, paramName + " can&#39;t be null");
  }

  /// <summary>
  /// 请检查参数1不同于参数2
  /// </summary>
  /// <param name="param1">值1测试</param>
  /// <param name="param1Name">name of value 1</param>
  /// <param name="param2">value 2 to test</param>
  /// <param name="param2Name">name of vlaue 2</param>
  public static void CheckDifferentsParams(object param1, string param1Name, object param2, string param2Name)
  {
   if (param1 == param2) {
    throw new ArgumentException(param1Name + " can&#39;t be the same as " + param2Name,
     param1Name + " and " + param2Name);
   }
  }

  /// <summary>
  /// 检查一个整数值是正的(0或更大)
  /// </summary>
  /// <param name="val">整数测试</param>
  public static void PositiveValue(int val)
  {
   if (val < 0)
    throw new ArgumentException("The value must be greater than or equal to 0.");
  }
登入後複製

(3).Try-Catch扩展操作:


  /// <summary>
  ///  对某对象执行指定功能与后续功能,并处理异常情况
  /// </summary>
  /// <typeparam name="T">对象类型</typeparam>
  /// <param name="source">值</param>
  /// <param name="action">要对值执行的主功能代码</param>
  /// <param name="failureAction">catch中的功能代码</param>
  /// <param name="successAction">主功能代码成功后执行的功能代码</param>
  /// <returns>主功能代码是否顺利执行</returns>
  public static bool TryCatch<T>(this T source, Action<T> action, Action<Exception> failureAction,
   Action<T> successAction) where T : class
  {
   bool result;
   try
   {
    action(source);
    successAction(source);
    result = true;
   }
   catch (Exception obj)
   {
    failureAction(obj);
    result = false;
   }
   return result;
  }

  /// <summary>
  ///  对某对象执行指定功能,并处理异常情况
  /// </summary>
  /// <typeparam name="T">对象类型</typeparam>
  /// <param name="source">值</param>
  /// <param name="action">要对值执行的主功能代码</param>
  /// <param name="failureAction">catch中的功能代码</param>
  /// <returns>主功能代码是否顺利执行</returns>
  public static bool TryCatch<T>(this T source, Action<T> action, Action<Exception> failureAction) where T : class
  {
   return source.TryCatch(action,
    failureAction,
    obj => { });
  }

  /// <summary>
  ///  对某对象执行指定功能,并处理异常情况与返回值
  /// </summary>
  /// <typeparam name="T">对象类型</typeparam>
  /// <typeparam name="TResult">返回值类型</typeparam>
  /// <param name="source">值</param>
  /// <param name="func">要对值执行的主功能代码</param>
  /// <param name="failureAction">catch中的功能代码</param>
  /// <param name="successAction">主功能代码成功后执行的功能代码</param>
  /// <returns>功能代码的返回值,如果出现异常,则返回对象类型的默认值</returns>
  public static TResult TryCatch<T, TResult>(this T source, Func<T, TResult> func, Action<Exception> failureAction,
   Action<T> successAction)
   where T : class
  {
   TResult result;
   try
   {
    var u = func(source);
    successAction(source);
    result = u;
   }
   catch (Exception obj)
   {
    failureAction(obj);
    result = default(TResult);
   }
   return result;
  }

  /// <summary>
  ///  对某对象执行指定功能,并处理异常情况与返回值
  /// </summary>
  /// <typeparam name="T">对象类型</typeparam>
  /// <typeparam name="TResult">返回值类型</typeparam>
  /// <param name="source">值</param>
  /// <param name="func">要对值执行的主功能代码</param>
  /// <param name="failureAction">catch中的功能代码</param>
  /// <returns>功能代码的返回值,如果出现异常,则返回对象类型的默认值</returns>
  public static TResult TryCatch<T, TResult>(this T source, Func<T, TResult> func, Action<Exception> failureAction)
   where T : class
  {
   return source.TryCatch(func,
    failureAction,
    obj => { });
  }
登入後複製

本文没有具体介绍try,catch,finally的使用,而是给出一些比较通用的方法,主要是一般的开发者对于三个块的使用都有一个认识,就不再做重复的介绍。

三.DotNET的Exception类分析:

CLR允许异常抛出任何类型的实例,这里我们介绍一个System.Exception类:

1.Message属性:指出抛出异常的原因。


[__DynamicallyInvokable]
public virtual string Message
{
 [__DynamicallyInvokable]
 get
 {
  if (this._message != null)
  {
   return this._message;
  }
  if (this._className == null)
  {
   this._className = this.GetClassName();
  }
  return Environment.GetRuntimeResourceString("Exception_WasThrown", new object[] { this._className });
 }
}
登入後複製

由以上的代码可以看出,Message只具有get属性,所以message是只读属性。GetClassName()获取异常的类。GetRuntimeResourceString()获取运行时资源字符串。

2.StackTrace属性:包含抛出异常之前调用过的所有方法的名称和签名。


public static string StackTrace
{
 [SecuritySafeCritical]
 get
 {
  new EnvironmentPermission(PermissionState.Unrestricted).Demand();
  return GetStackTrace(null, true);
 }
}
登入後複製

EnvironmentPermission()用于环境限制,PermissionState.Unrestricted设置权限状态,GetStackTrace()获取堆栈跟踪,具体看一下GetStackTrace()的代码。


internal static string GetStackTrace(Exception e, bool needFileInfo)
{
 StackTrace trace;
 if (e == null)
 {
  trace = new StackTrace(needFileInfo);
 }
 else
 {
  trace = new StackTrace(e, needFileInfo);
 }
 return trace.ToString(StackTrace.TraceFormat.Normal);
}
登入後複製


public StackTrace(Exception e, bool fNeedFileInfo)
{
 if (e == null)
 {
  throw new ArgumentNullException("e");
 }
 this.m_iNumOfFrames = 0;
 this.m_iMethodsToSkip = 0;
 this.CaptureStackTrace(0, fNeedFileInfo, null, e);
}
登入後複製

以上是获取堆栈跟踪方法的具体实现,此方法主要用户调试的时候。

3.GetBaseException()获取基础异常信息方法。


[__DynamicallyInvokable]
public virtual Exception GetBaseException()
{
 Exception innerException = this.InnerException;
 Exception exception2 = this;
 while (innerException != null)
 {
  exception2 = innerException;
  innerException = innerException.InnerException;
 }
 return exception2;
}
登入後複製

InnerException属性是内在异常,这是一个虚方法,在这里被重写。具体看一下InnerException属性。


[__DynamicallyInvokable]
public Exception InnerException
{
 [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
 get
 {
  return this._innerException;
 }
}
登入後複製

4.ToString()将异常信息格式化。


private string ToString(bool needFileLineInfo, bool needMessage)
{
 string className;
 string str = needMessage ? this.Message : null;
 if ((str == null) || (str.Length <= 0))
 {
  className = this.GetClassName();
 }
 else
 {
  className = this.GetClassName() + ": " + str;
 }
 if (this._innerException != null)
 {
  className = className + " ---> " + this._innerException.ToString(needFileLineInfo, needMessage) + Environment.NewLine + " " + Environment.GetRuntimeResourceString("Exception_EndOfInnerExceptionStack");
 }
 string stackTrace = this.GetStackTrace(needFileLineInfo);
 if (stackTrace != null)
 {
  className = className + Environment.NewLine + stackTrace;
 }
 return className;
}
登入後複製

在此方法中,将获取的异常信息进行格式化为字符串,this.GetClassName() 获取异常类的相关信息。

以上我们注意到[__DynamicallyInvokable]定制属性,我们看一下具体的实现代码:


[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public __DynamicallyInvokableAttribute()
{
}
登入後複製

以上我们主要注释部分,”图像边界“这个属性的相关信息,请参见《Via CLR c#》,这里就不做具体的介绍。

四.总结:

以上在对异常的介绍中,主要介绍了CLR的异常处理机制,一些较为通用的异常代码,以及对Exception类的介绍。在实际的项目中,我们一般不要将异常直接抛出给客户,我们在编写程序时,已经考虑程序的容错性,在程序捕获到异常后,尽量去恢复程序,或者将异常信息写入日志,让程序进入错误页。如果出现比较严重的异常,最后将异常抛出,终止程序。

以上是分析.NET的例外處理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1424
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
WIN10服務主機太佔cpu的處理操作過程 WIN10服務主機太佔cpu的處理操作過程 Mar 27, 2024 pm 02:41 PM

1.首先我們右鍵點選任務列空白處,選擇【任務管理器】選項,或右鍵開始徽標,然後再選擇【任務管理器】選項。 2.在開啟的任務管理器介面,我們點選最右邊的【服務】選項卡。 3.在開啟的【服務】選項卡,點選下方的【開啟服務】選項。 4.在開啟的【服務】窗口,右鍵點選【InternetConnectionSharing(ICS)】服務,然後選擇【屬性】選項。 5.在開啟的屬性窗口,將【開啟方式】修改為【禁用】,點選【應用程式】後點選【確定】。 6.點選開始徽標,然後點選關機按鈕,選擇【重啟】,完成電腦重啟就行了。

浪人崛起水池的異常任務攻略 浪人崛起水池的異常任務攻略 Mar 26, 2024 pm 08:06 PM

水池的異常是遊戲中一個支線任務,很多玩家想知道水池的異常任務怎麼完成,其實非常簡單,首先我們要掌握在水中拍攝的技術,才可以接取任務,調查惡臭味的來源,之後發現原來是水池底下有很多的屍體,具體內容一起來看看這篇浪人崛起水池的異常任務圖文攻略。浪人崛起水池的異常任務攻略1、和飯塚對話,學習在水中拍攝的技術。 2、前往下圖位置接取水池的異常任務。 3.來到任務地點和NPC對話,了解到附近的水池有一股惡臭味。 4、前往水池調查。 5.大概游到下圖位置,潛入到水下,會發現很多的屍體。 6.使用相機對屍體進行拍攝。 7

學習PHP中如何處理特殊字元轉換單引號 學習PHP中如何處理特殊字元轉換單引號 Mar 27, 2024 pm 12:39 PM

在PHP開發過程中,處理特殊字元是常見的問題,尤其是在字串處理中經常會遇到特殊字元轉義的情況。其中,將特殊字元轉換單引號是比較常見的需求,因為在PHP中,單引號是一種常用的字串包裹方式。在本文中,我們將介紹如何在PHP中處理特殊字元轉換單引號,並提供具體的程式碼範例。在PHP中,特殊字元包括但不限於單引號(')、雙引號(")、反斜線()等。在字串

MIT最新力作:以GPT-3.5解決時間序列異常檢測問題 MIT最新力作:以GPT-3.5解決時間序列異常檢測問題 Jun 08, 2024 pm 06:09 PM

今天要為大家介紹一篇MIT上週發表的文章,使用GPT-3.5-turbo解決時間序列異常檢測問題,初步驗證了LLM在時間序列異常檢測的有效性。整個過程沒有進行finetune,直接使用GPT-3.5-turbo進行異常檢測,文中的核心是如何將時間序列轉換成GPT-3.5-turbo可辨識的輸入,以及如何設計prompt或pipeline讓LLM解決異常檢測任務。下面跟大家詳細介紹一下這篇工作。圖片論文標題:Largelanguagemodelscanbezero-shotanomalydete

C++ 函式異常與單測:確保程式碼健全性 C++ 函式異常與單測:確保程式碼健全性 May 03, 2024 am 09:18 AM

異常處理和單測是確保C++程式碼健全性的重要實務。異常透過try-catch區塊處理,當程式碼引發異常時會跳到catch區塊。單元測試可隔離程式碼測試,以驗證異常處理在不同情況下是否如預期運作。實戰案例:sumArray函數計算數組元素總和,並拋出異常以處理空輸入數組。單元測試可驗證函數在異常情況下的預期行為,如當數組為空時拋出std::invalid_argument異常。結論:透過利用異常處理和單測,我們可以處理異常情況、防止程式碼崩潰,並確保程式碼在異常情況下按預期運行。

分享幾個.NET開源的AI和LLM相關專案框架 分享幾個.NET開源的AI和LLM相關專案框架 May 06, 2024 pm 04:43 PM

當今人工智慧(AI)技術的發展如火如荼,它們在各個領域都展現了巨大的潛力和影響力。今天大姚給大家分享4個.NET開源的AI模型LLM相關的專案框架,希望能為大家提供一些參考。 https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel是一種開源的軟體開發工具包(SDK),旨在將大型語言模型(LLM)如OpenAI、Azure

C++ 函式異常進階:客製化錯誤處理 C++ 函式異常進階:客製化錯誤處理 May 01, 2024 pm 06:39 PM

C++中的異常處理可透過自訂異常類別增強,提供特定錯誤訊息、上下文資訊以及根據錯誤類型執行自訂操作。定義繼承自std::exception的異常類,提供特定的錯誤訊息。使用throw關鍵字拋出自訂異常。在try-catch區塊中使用dynamic_cast將捕獲到的異常轉換為自訂異常類型。在實戰案例中,open_file函數會拋出FileNotFoundException異常,捕捉並處理該異常可提供更具體的錯誤訊息。

如何在C++中實現巢狀異常處理? 如何在C++中實現巢狀異常處理? Jun 05, 2024 pm 09:15 PM

巢狀異常處理在C++中透過嵌套的try-catch塊實現,允許在異常處理程序中引發新異常。嵌套的try-catch步驟如下:1.外部try-catch區塊處理所有異常,包括內部異常處理程序拋出的異常。 2.內部try-catch區塊處理特定類型的異常,如果發生超出範圍的異常,則將控制權交給外部異常處理程序。

See all articles