代码之家  ›  专栏  ›  技术社区  ›  Femaref

catch()-阻塞作为流动方向(种类)

  •  0
  • Femaref  · 技术社区  · 16 年前

    我目前在我的项目中使用这样的代码块

         public ActionStatus GetStuff(out output)
         {
            try
            {
                if(!validation)
                  return ActionStatus.DataInvalid;
                //do possible error stuff here
                output = data;
                return ActionStatus.Successful;
            }
            catch
            {
                output = null;
                return ActionStatus.Failed;
            }
         }
    

    我使用这个,因为actionstatus枚举足够程序继续(这些东西最多从缓存或数据库读取数据),因为枚举提供足够的信息来向用户提供消息。这些方法将具有postsharp weaver属性,以记录消息以供以后调试使用。

    在我看来,这是一种处理此类非关键异常的好方法,因为枚举足以继续;另一方面,我总是有一句话“不要用异常控制您的程序流”,但我将其解释为使用

    if(ex == fooException)
      doThis();
    else if (ex == barException)
      doThat();
    

    你对此有什么看法?

    更新: 从我能看到的两个答案中,有必要进一步澄清,特别是关于后竖琴编织者。

    Postshap是一个面向方面的编程(AOP)框架,它基本上允许您创建类,这些类覆盖特定的方法,如OnEnter、OneXit、OnException等。 这允许您将特定(例如日志记录)代码保持在最低限度,您只需将 属性设置为要在compileTime修改的方法或类。这样,我就不会丢失任何异常信息,因为调用堆栈和其他一切都将保持不变。

    更新2: 错过了分配,必须分配out参数。

    2 回复  |  直到 15 年前
        1
  •  0
  •   John Rudy    16 年前

    基于OP更新的更新(AOP框架)

    您不知道我多么高兴地发现您使用的框架确保您不会丢失任何原始异常信息。这使我对你的设计感觉更好。

    然而,在这种情况下,我回到了@silky从他留在这里的评论中得到的建议,以及@mfx对这个问题本身的警告:为什么要费心去捕捉呢?您的软件设计依赖于更高级别的检查方法的返回值。开发人员很容易错过或忘记这样做。至少,如果异常在堆栈中冒泡并发生,那么可以在测试中注意到它,并调整代码。如果不检查返回值,bug可能会变得更加阴险。

    我再次向您介绍Microsoft关于异常处理的开发人员框架指南。(在我强烈推荐的带注释的书的形式中,有很多关于为什么做出设计决策的注释,包括关于为什么他们决定——通常——避开返回代码而赞成异常的注释。)

    关于您的(更新的)代码,为什么这不是一个可接受的重新设计?

     public WhateverTypeOutputWas GetStuff()
     {
        if(!validation)
            return ActionStatus.DataInvalid;
        //do possible error stuff here
        return data;
     }
    

    这里我们有一个异常,在堆栈中冒泡,以便更高级别的处理,而不可能忽略返回代码。

    按照问题中的代码编写方式,如果开发人员忘记检查您的状态代码,他可能会得到一个nullreferenceexception。在这种情况下,为什么需要状态代码?开发人员能否安全地假定 output 意味着一次成功的跑步?在上面的设计中,我们去掉了方法的一半,正确地冒泡异常,正确地使用返回值(根据微软的框架设计指南),并为使用这种方法的开发人员简化了生命。赢得胜利。

    原始答案

    你为什么要把你捕获的异常中包含的有价值的信息去掉?重新播放:

    catch(Exception ex)
    {
        // Any handling (like logging, etc.) here
        // If no handling, don't bother catching
        throw;
    }
    

    并且允许更高层的代码捕获并确定向用户显示什么(如果有),并且(希望)在需要时记录详细信息。

    场合 在这种情况下,可以这样做,但根据我的经验,它们很少而且相距甚远——对于我来说,完全丢弃异常通常是非常不重要的一段代码,不管喜欢与否,这就是这里发生的事情。

    将异常视为控制流,我不认为(从您最初的问题中)会认为:

    if(ex == fooException)
      doThis();
    else if (ex == barException)
      doThat();
    

    我认为,将异常作为控制流的设计指南实际上是将抛出异常作为一种早期脱离循环的方法(而不是使用 break 例如),在代码中没有出错时使用异常,如简单的早期返回等。

    我指给你看微软的官方 Design Guidelines for Exceptions ;因为这是我在工作过程中试图遵循的,我希望与我一起工作的开发人员也这样做。(也就是说,除非我们有 真的? 好的,有记录的理由不去。再说一遍,这些是 罕见。 )

    请记住,异常是针对代码中的异常事件——通常是错误条件。我们不希望检查.NET基类库中的成功/失败代码是有原因的,.NET中的首选模型是,如果方法未能执行,则抛出异常。因此,错误处理被降级为 try / catch 返回代码用于将有用的数据返回到使用您的方法的客户机代码。

        2
  •  0
  •   Noon Silk    16 年前

    我认为你的模型很合理。

    “异常情况下不控制程序流”这句话有点奇怪,因为这正是您 应该 正在做。如果你继续这样做,就好像例外从未发生过一样,那么我无法想象你在做什么!:)

    我也同意,你的“如果”声明建议是非常荒谬的,任何这样做的人都应该被枪毙。

    但是,当然,有点像

    try {
    }
    catch(SomeException e) { }
    catch(Exception e){ }
    

    是合理的。

    --编辑:

    更新以确认我认为你的AOP与此无关;不管怎样,这是相当合理的。