关于.NET异常处理的沉思。关于.NET异常处理的想想(上)

以上是在实际开发中需要面对的问题,以上是在实际开发中需要面对的问题

   
年关用至,对于大部分程序员来说,马上就是好闲下来一段时间了,然而当是闲暇之日子里,唯有争论哪门语言更好得消磨时光,估计最近见面发成百上千关于java与.net的博文出现,我代表只要作一个吃瓜群众,静静的拘留在大佬们上心情。

   

    以上之废话说的够多矣,这里就不再赘言了,还是切入主题吧。

   
年关以到,对于大部分程序员来说,马上就是可闲下来一段时间了,然而以这个闲暇之光阴里,唯有争论哪门语言更好得消磨时光,估计最近会见发出多关于java与.net的博文出现,我代表要作为一个吃瓜群众,静静的关押在大佬们上心情。

   
在档次开支被,对于系及代码的安宁与容错性都是有对应的求。实际支出品种蒙之代码和样例代码的别,更多之是于代码的运作的稳定性、容错性、扩展性的可比。因为对此贯彻一个效能来说,实现力量的主干代码是一律的,可能只是于写法上优化而已,但是当落实有一个操作及采取的好像来说,这一点凡是多数时刻是平的。这样看来,我们当实际上付出的历程被,需要考虑的题目较多,已经不仅仅局限为某某平等实际的效能实现,更多之是代码的安澜以及扩展性考虑。

    以上之废话说的够用多了,这里虽不再赘述了,还是切入主题吧。

   
以上是当其实开发被待直面的题目,笔者于近来底博文被,也在设想是充分到底需要怎么去描绘,以及生到底要怎么去领悟,在博文中,也起无数的园友对那个的写法与处理提出了团结的见地,在此地自己虽描写一下自己之一对清楚,可能勾的于浅显和精炼,但是一味当是一个引子,可以引出大佬们来谈谈自己的实际项目更。希望对大家来一个赞助,也欢迎大家提出好的想法及意见,分享温馨之知和眼光。

   
在类型开发中,对于网及代码的安居乐业以及容错性都是有相应之要求。实际支付品种面临的代码和样例代码的别,更多之是以代码的运转的长治久安、容错性、扩展性的可比。因为对贯彻一个功效来说,实现力量的主干代码是同一的,可能只是以写法上优化而已,但是在实现有一个操作及行使的好像来说,这一点凡是大多数时分是同等的。这样看来,我们在实际上支出的进程遭到,需要考虑的题材比多,已经不仅仅局限为某某平等切实可行的功力实现,更多的凡代码的风平浪静和扩展性考虑。

一.DotNET好的概述:

   
谈到那个,我们尽管用理解啊叫做异常,万事万物如果我们怀念去学,就相应知道我们而读书的物是啊,这样以心尖可有一个盖的回味。异常是赖成员没有做到她的号宣称可形成的走。在.NET中,构造器、获取与安装属性、添加和去事件、调用操作符重载和调用转换操作符等等都未曾办法回去错误代码,但是以这些组织中还要要报错误,那即便非得提供十分处理机制。

   
在死的处理着,我们常用到的老三个片分别是:try块;catch块;finally块。这三单片好联手下,也可不写catch块使用,异常处理块好嵌套使用,具体的办法在脚会介绍到。

   
在老的拍卖机制中,一般生三栽选择:重新抛来一致之不行,向调用栈高一重叠的代码通知该特别的发;抛出一个例外之很,想调用栈高一层代码提供更丰富的挺信息;让线程从catch块的底退出。 
 

   有关好的处理方式,有一对指导性的提议。

   
以上是于事实上开发被待面对的题材,笔者于近年之博文中,也在设想是大到底需要怎么去描绘,以及老到底要怎么去领悟,在博文中,也产生许多底园友对异常的写法和拍卖提出了友好之见识,在此地自己就形容一下和谐之片了然,可能勾的可比浅显和精炼,但是单独当是一个引子,可以引出大佬们来讨论自己之实在项目阅。希望对大家来一个声援,也接大家提出自己之想法跟看法,分享自己的知以及意见。

       1.适龄的使用finally块:

         
 finally块可以保证不管线程抛来什么种的老都好吃实施,finall块一般用来做清理那些已经成功启动的操作,然后又回来调用者或者finally块之后的代码。

一.DotNET老大的概述:

   
谈到非常,我们就是需懂得什么叫异常,万事万物如果我们怀念去念,就当理解我们只要读之东西是什么,这样在心底同意有一个盖的体味。异常是指成员没有完结其的称宣称可完成的步。在.NET中,构造器、获取和安装属性、添加和去事件、调用操作符重载和调用转换操作符等等都不曾主意回到错误代码,但是于这些构造中以欲报错误,那便亟须提供好处理体制。

   
在好的处理着,我们常常以到的老三单片分别是:try块;catch块;finally块。这三独片好共以,也可免写catch块使用,异常处理块好嵌套使用,具体的点子以底下会介绍至。

   
在异常的处理机制面临,一般有三种植选择:重新抛来同样之杀,向调用栈高一重叠的代码通知该特别的生;抛出一个不比之慌,想调用栈高一重合代码提供再丰富的不可开交信息;让线程从catch块的底层退出。 
 

   有关好的处理方式,有局部指导性的建议。

       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);
            }

       1.适宜的采取finally块:

         
 finally块可以包不管线程抛来什么品种的充分且得为执行,finall块一般用来开清理那些都成启动之操作,然后再返回调用者或者finally块之后的代码。

       3.由十分中还原:

         
 我们于破获异常后,可以本着的写有可怜恢复的代码,可以让程序继续运行。在抓获异常时,需要捕获具体的雅,充分的支配在啊情况下会废弃来老,并懂得从捕获的杀类型派生出了那些类型。除非在catch块的终极重新抛来怪,否则不要处理或者捕获System.Exception异常。

       2.雅捕捉消适度:

         
 为什么而得当的捕捉异常与否?如下代码,因为我们不可知呀坏且失去捕捉,在抓获异常后,我们得去处理这些大,如果我们用拥有的要命都捕捉后,但是没预见会有的不得了,我们就算没有办法去处理这些好。

       
 如果应用程序代码抛来一个好,应用程序的另外一样端则恐预期而捕捉这个很,因此无能够写成一个”大小通吃“的杀块,应该允许该老在调用栈中向上走,让应用程序代码针对性地拍卖这个大。

       
 在catch块中,可以使System.Exception捕捉异常,但是最为好当catch块末尾重新抛来好。至于因在末端会讲课到。

图片 1

          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);
            }

图片 2

      4.维持状态:

         
一般景象下,我们完成一个操作还是一个智时,需要调用几个主意结合得,在实施之过程被会产出前几独道就,后面的办法来很。发生不可恢复的很时回滚部分成功的操作,因为咱们要恢复信息,所有我们当抓获异常时,需要捕获所有的生信息。

       3.于深中还原:

         
 我们于捕获异常后,可以对的描摹有雅恢复的代码,可以给程序继续运行。在捕获异常时,需要捕获具体的慌,充分的牵线在什么状况下会扔来十分,并明白从捕获的死去活来类型派生出了那些类型。除非在catch块的结尾重新抛来老,否则不要处理要捕获System.Exception异常。

      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。

      4.保持状态:

         
一般情况下,我们成功一个操作还是一个主意时,需要调用几独艺术结合形成,在执行之长河被见面并发前几单方法好,后面的措施来特别。发生不可恢复的百般时回滚部分形成的操作,因为咱们得恢复信息,所有我们在捕获异常时,需要捕获所有的要命信息。

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

     
在代码有甚后,我们要去处理者很,如果一个深没有拿走这的处理,CLR会终止进程。在怪的拍卖面临,我们得于一个线程捕获异常,在旁一个线程中再度抛来怪。异常抛来时,CLR会在调用栈中向上查找和抛来之杀类型匹配的catch块。如果无其余catch块匹配抛来底慌类型,就生出一个勿处理非常。CLR检测到过程中之另外线程有一个位处理非常,都见面终止进程。

      5.潜伏实现细节来保持契约:

         
有时可能得捕捉一个老大并还抛来一个两样之百般,这样好保方法的契约,抛来的私心甚类型地应当是一个有血有肉的那个。看如下代码:

图片 3

FileStream fs = null;
            try
            {
                fs = FileStream();

            }
            catch (FileNotFoundException e)
            {
          //抛出一个不同的异常,将异常信息包含在其中,并将原来的异常设置为内部异常
                throw new NameNotFoundException();
            }
            catch (IOException e)
            {

               //抛出一个不同的异常,将异常信息包含在其中,并将原来的异常设置为内部异常

             throw new NameNotFoundException(); 
            } 
            finally 
            {
               if (fs != null) 
                { 
               fs.close(); 
            } 
            }

图片 4

   
 以上之代码只是于说明一种处理方式。应该给弃来底兼具大且挨方法的调用栈向上传递,而休是将她们”吞噬“了随后丢弃来一个新的深。如果一个档构造器抛来一个怪,而且该特别未当路构造器方法中抓获,CLR就会当其中捕获该生,并转也废除来一个初的TypeInitialztionException。

     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块之后的言辞开始执行。

     
备注:异常片好构成以及嵌套,对于三个要命块的样例,在此处就不开牵线,异常的嵌套可以防范以处理好的时候再次出现未处理的大,以上这些就不再赘述。

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

     
在代码有甚后,我们得去处理者特别,如果一个那个没有得到这的处理,CLR会终止进程。在特别的拍卖中,我们好以一个线程捕获异常,在其他一个线程中更抛来好。异常抛来时,CLR会在调用栈中向上查找和抛来的老大类型匹配的catch块。如果无其余catch块匹配抛来的不行类型,就生一个不处理好。CLR检测及过程面临的别样线程有一个各处理非常,都见面停进程。

    2.非常处理实例:

     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块之后的语句开始实践。

     
备注:异常块好做及嵌套,对于三只很块的样例,在这里就是未开牵线,异常的嵌套可以防止以处理好的时刻再次出现未处理的要命,以上这些虽不再赘言。

       (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.特别处理实例:

     (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'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'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'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'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.");
        }
       (1).异常处理扩展方法:

图片 5

        /// <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();
        }

图片 6

     (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的动,而是让来有于通用的道,主要是形似的开发者对于三只片的利用还起一个认识,就不再做重新的牵线。

     (2).验证异常:

图片 7

       /// <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'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'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'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'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.");
        }

图片 8

三.DotNET的Exception类分析:

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

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

图片 9

        /// <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 => { });
        }

图片 10

   
 本文没有实际介绍try,catch,finally的采用,而是给来一部分较通用的方式,主要是相似的开发者对于三只片的用还有一个认识,就不再做还的介绍。

      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()获取运行时资源字符串。

三.DotNET的Exception类分析:

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

     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);
}

      以上是获取堆栈跟踪办法的切实落实,此方法主要用户调试之上。

      1.Message属性:指出抛来怪的缘故。

图片 11

[__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 });
    }
}

图片 12

   
由上述之代码可以见到,Message只拥有get属性,所以message是一味读属性。GetClassName()获取很的切近。GetRuntimeResourceString()获取运行时资源字符串。

     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;
    }
}

     2.StackTrace属性:包含抛来特别之前调用了的有方的称谓与签字。

图片 13

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

图片 14

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

图片 15

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);
}

图片 16

图片 17

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);
}

图片 18

      以上是获取堆栈跟踪办法的现实性实现,此道要用户调试的时。

    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#》,这里虽未做具体的介绍。

     3.GetBaseException()获取基础很信息法。

图片 19

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

图片 20

 
  InnerException属性是外于异常,这是一个虚方法,在此处吃重写。具体看一下InnerException属性。

图片 21

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

图片 22

四.总结:

 
 以上在对特别的介绍中,主要介绍了CLR的死去活来处理机制,一些比较通用的非常代码,以及对Exception类的牵线。在实际的门类中,我们一般不要将很直白丢弃来为客户,我们当编写程序时,已经考虑次的容错性,在先后捕获到大后,尽量去恢复程序,或者用坏信息写副日志,让程序上错误页。如果出现比较严重的很,最后以格外抛来,终止程序。

    4.ToString()将不胜信息格式化。

图片 23

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;
}

图片 24

     在斯道吃,将取得的雅信息进行格式化为字符串,this.GetClassName()
获取很类的相干消息。

   
 以上我们注意到[__DynamicallyInvokable]定制性,我们看一下实际的贯彻代码:

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

   以上我们任重而道远注释部分,”图像边界“这个特性之连锁消息,请参见《Via CLR
c#》,这里就是不举行实际的牵线。

四.总结:

 
 以上在针对充分的介绍中,主要介绍了CLR的很处理机制,一些较为通用的挺代码,以及对Exception类的牵线。在事实上的色受到,我们一般不要用不胜直白丢掉来为客户,我们当编写程序时,已经考虑次的容错性,在程序捕获到死后,尽量去恢复程序,或者将颇信息写副日志,让程序上错误页。如果起比较严重的怪,最后用老抛来,终止程序。

原文链接:http://www.cnblogs.com/pengze0902/p/6185952.html


感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文欢迎各位转载,但是转载文章之后必须在文章页面中给出作者和原文连接。如果需要获取最新的优秀.NET博文,请关注微信公众号“DotNet技术分享”。 

图片 25.jpg)

好知求真,静心钻研,虚心学习,务实创新,细致和。

 

 

标签: c#,
特别处理,
Exception