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

关于.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块末尾重新抛来深。至于因在后头会讲课到。

betway必威 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);
            }

betway必威 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.掩蔽实现细节来保持契约:

         
有时可能得捕捉一个异常并更抛来一个例外之不可开交,这样可以保方法的契约,抛来之心里死类型地当是一个具体的特别。看如下代码:

betway必威 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(); 
            } 
            }

betway必威 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).异常处理扩展方法:

betway必威 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();
        }

betway必威 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).验证异常:

betway必威 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.");
        }

betway必威 8

三.DotNET的Exception类分析:

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

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

betway必威 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 => { });
        }

betway必威 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属性:指出抛来异常的由来。

betway必威 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 });
    }
}

betway必威 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属性:包含抛来好之前调用了的装有术的称号与署名。

betway必威 13

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

betway必威 14

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

betway必威 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);
}

betway必威 16

betway必威 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);
}

betway必威 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()获取基础好信息方式。

betway必威 19

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

betway必威 20

 
  InnerException属性是外当大,这是一个虚方法,在此地让重写。具体看一下InnerException属性。

betway必威 21

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

betway必威 22

四.总结:

 
 以上在针对充分的介绍着,主要介绍了CLR的可怜处理体制,一些较为通用的不得了代码,以及对Exception类的牵线。在其实的类受到,我们一般不要用不胜直白扔来给客户,我们当编写程序时,已经考虑次的容错性,在次捕获到非常后,尽量错开恢复程序,或者将颇信息写副日志,让程序上错误页。如果起比较严重的大,最后将生抛来,终止程序。

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

betway必威 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;
}

betway必威 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技术分享”。 

betway必威 25.jpg)

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

 

 

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

admin

网站地图xml地图