快捷搜索:

关于.NET异常处理的思考

来源:http://www.shanghai-sourcing.com 作者:网页版吃鸡 人气:192 发布时间:2019-11-21
摘要:   年关将至,对于超过百分之五十程序猿来讲,立刻就足以闲下来生机勃勃段时间了,但是在这里个闲暇的时刻里,只有争辨哪门语言越来越好能够消磨时光,估量前段时间会有超级

    年关将至,对于超过百分之五十程序猿来讲,立刻就足以闲下来生机勃勃段时间了,但是在这里个闲暇的时刻里,只有争辨哪门语言越来越好能够消磨时光,估量前段时间会有超级多关于java与.net的博文现身,小编代表要作为二个吃瓜群众,静静的望着大佬们公布心情。

    以上的废话说的够多了,这里就不再赘言了,依然切入宗旨吧。

关于.NET异常处理的思考。    在类型支付中,对于系统和代码的安宁和容错性都以有相应的渴求。实际支出项目中的代码与样例代码的界别,更加的多的是在代码的周转的波平浪静、容错性、扩充性的相比。因为对于得以实现几个职能来讲,实现效果与利益的主导代码是同后生可畏的,也许只是在写法上优化而已,不过在促成某一个操作上选拔的类来讲,这点是相当多时候是生龙活虎致的。那样看来,我们在事实上开销的长河中,需求思虑的主题材料比较多,已经不止局限于某一切实的作用达成,越来越多的是代码的平安定协调扩张性思忖。

    以上是在实际上开辟中须要直面的问题,笔者在近来的博文中,也在思谋那个特别到底要求怎么去写,以致这几个到底必要怎么去精通,在博文中,也可能有多数的园友对至极的写法和管理提议了友好的观念,在这里间自个儿就写一下融洽的有的知晓,只怕写的可比浅显和简单,不过只当是贰个引子,能够引出大佬们来斟酌本身的莫过于项目阅历。希望对大家有一个援助,也应接大家建议自身的主张和观念,分享温馨的文化和见解。

少年老成.DotNET老大的概述:

    说到丰裕,大家就要求了解哪些叫做万分,万事万物假设我们想去学习,就应有明了大家要读书的事物是怎么,那样在心尖同意有三个大致的体会。至极是指成员未能如愿它的名目宣称能够成功的行走。在.NET中,构造器、获取和设置属性、增多和删除事件、调用操作符重载和调用调换操作符等等都并没法回去错误代码,可是在这里些构造中又需求报告错误,那就务须提供特别处理体制。

    在非常的拍卖中,大家经常应用到的三个块分别是:try块;catch块;finally块。那八个块能够生机勃勃并使用,也能够不写catch块使用,极度管理块能够嵌套使用,具体的格局在底下会介绍到。

    在十二分的管理机制中,日常常有三种采取:重新抛出同样的可怜,向调用栈高生机勃勃层的代码公告该极其的产生;抛出二个不一致的特别,想调用栈高风姿浪漫层代码提供更足够的极度音讯;让线程从catch块的尾部退出。   

   有关十分的管理形式,有风流罗曼蒂克对引导性的建议。

关于.NET异常处理的思考。       1.适宜的施用finally块:

           finally块能够保险不管线程抛出什么项指标至极都足以被实行,finall块平日用来做清理那一个已经成功运行的操作,然后再回到调用者只怕finally块之后的代码。

       2.百般捕捉需适度:

           为何要适用的捕捉非凡呢?如下代码,因为我们不可能怎样特别都去捕捉,在捕获卓殊后,大家需求去管理那几个相当,假若我们将持有的特别都捕捉后,然则未有预言会生出的十二分,大家就从未章程去管理那几个十分。

关于.NET异常处理的思考。         假诺应用程序代码抛出一个老大,应用程序的另豆蔻梢头端则恐怕预期要捕捉那个非常,因此不可能写成三个”大小通吃“的不得了块,应该允许该极其在调用栈中向上移动,让应用程序代码指向性地拍卖这些非常。

         在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.保持状态:

关于.NET异常处理的思考。          平日景色下,我们做到三个操作仍旧一个方法时,须求调用多少个艺术结合产生,在实践的长河中会现身前边多少个形式成功,前面包车型客车方法发生极其。爆发不可恢复生机的要命时回滚部分成功的操作,因为大家必要还原音信,全体大家在抓获至极时,供给捕获全体的可怜新闻。

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

     以上的代码只是在验证风姿洒脱种管理方式。应该让抛出的有所特别都沿着方法的调用栈向上传递,并不是把他们”吞吃“精通后抛出三个新的丰盛。借使三个类型构造器抛出一个至极,並且该非常未在类型构造器方法中抓获,CL冠道就能够在其间捕获该极度,并改为抛出二个新的TypeInitialztionException。

二.DotNET相当的常用项理体制:

      在代码发生极度后,我们要求去管理那几个丰硕,要是三个非常未有收获及时的管理,CL奥迪Q3会终止进度。在十分的拍卖中,我们得以在一个线程捕获万分,在另三个线程中再一次抛出特别。格外抛出时,CLRAV4会在调用栈中向上查找与抛出的不得了类型相配的catch块。若无此外catch块相配抛出的卓殊类型,就时有产生一个未管理相当。CLCRUISER检验到进程中的任何线程有八个位管理极度,都会告生机勃勃段落进度。

     1.非常管理块:

       (1).try块:满含代码常常需求实施一些通用的能源清理操作,或然供给从十三分中平复,可能两个都亟待。try块还是可以包含只怕会抛出极其的代码。叁个try块至罕有一个关乎的catch块或finall块。       

       (2).catch块:富含的是响应三个非常需求推行的代码。catch关键字后的圆括号中的表达式是捕获类型。捕获类型从System.Exception或然其派生类钦点。CL索罗德自上而下搜素一个相配的catch块,所以应该教具体的相当放在最上端。意气风发旦CLSportage找到三个存有十分捕获类型的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'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.");
        }
     (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类分析:

        CL大切诺基允许极度抛出任何项目的实例,这里大家介绍二个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 CLXC60c#》,这里就不压实际的介绍。

四.总结:

   以上在对充裕的介绍中,重要介绍了CLKoleos的不行管理机制,一些相比通用的可怜代码,以至对Exception类的牵线。在事实上的品类中,我们常常不要将特别直白抛出给顾客,我们在编写程序时,已经构思程序的容错性,在前后相继捕获到特别后,尽量去复苏程序,大概将不胜消息写入日志,让程序步入错误页。假若现身相比较严重的十分,最后将那些抛出,终止程序。

本文由金沙澳门官网55网址发布于网页版吃鸡,转载请注明出处:关于.NET异常处理的思考

关键词:

上一篇:网页版吃鸡游记|壮哉,绥德汉!

下一篇:没有了

最火资讯