澳门蒲京网址关于.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