我目前正在项目中使用这些代码块
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枚举足以让程序继续(这些东西大多数时候都是从Cache或Database中读取数据),因为enum提供了足够的信息来向用户提供消息。这些方法将具有PostSharp-Weaver属性,以记录消息以供以后调试使用。
在我看来,这是一种处理此类非关键异常的好方法,因为枚举足以继续;另一方面,我总是说“不要用例外来控制你的程序流程”,但我将其解释为使用
if(ex == fooException)
doThis();
else if (ex == barException)
doThat();
您对此有何看法?
更新:关闭我可以看到的两个答案,需要进一步澄清,特别是关于PostSharp-weaver。
PostSharp是一个面向方面编程(AOP)框架,它基本上允许您创建覆盖特定方法的类,如OnEnter,OnExit,OnException等。 这使您可以将特定(例如,日志记录)代码保持在最低限度,您只需要输入一个 属性到您要在编译时修改的方法或类。通过这种方式,我不会丢失任何异常信息,因为callstack和其他所有内容仍然是相同的。
更新2 错过了作业,必须分配参数。
答案 0 :(得分:0)
您不知道我有多高兴发现您使用的框架可确保您不会丢失任何原始异常信息。这让我对你的设计感觉有点好。
然而,在那种情况下,我从他留下的评论中回到了@ silky的建议,以及@mfx关于问题本身的警示:为什么要费心去抓?您的软件设计依赖于更高级别检查方法的返回值。开发人员很容易错过或忘记这样做。至少如果异常在堆栈中冒泡并且发生,则可以在测试中注意到并且代码被调整。如果未检查返回值,则错误会变得更加隐蔽。
再次,我向您指出Microsoft关于异常处理的开发人员框架指南。 (在带注释的书籍表格中 - 我强烈推荐 - 有很多关于为什么做出设计决定的说明,包括关于他们为什么决定的说明 - 通常 - 回避有利于例外的返回代码。)
关于您的(更新的)代码,为什么这不是可接受的重新设计?
public WhateverTypeOutputWas GetStuff()
{
if(!validation)
return ActionStatus.DataInvalid;
//do possible error stuff here
return data;
}
我们在这里得到的是异常冒泡堆栈,以便处理更高级别,而不会忽略返回码。
在问题中编写代码的方式,如果他忘记检查您的状态代码,开发人员会听到NullReferenceException。在这种情况下,为什么需要状态代码呢?开发人员可以安全地假设任何output
的非空返回意味着成功运行吗?通过上面的设计,我们减少了一半的方法,正确地冒充了异常,正确使用返回值(根据Microsoft的框架设计指南)并简化了使用此方法的开发人员的生活。双赢。
为什么要删除您捕获的异常中包含的有价值信息?反思它:
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
,EG),在代码中没有出错时使用异常简单的早期退货等。
我指向微软的官方Design Guidelines for Exceptions;因为这是我在工作过程中尝试遵循的,我希望与我合作的开发人员也能这样做。 (也就是说,除非我们有一个真的好的,有记录的理由不这样做。再次,那些罕见。)
请记住,例外是针对代码中的异常事件 - 通常是错误条件。我们不希望检查.NET基类库中的成功/失败代码是有原因的 - .NET中的首选模型是在方法失败时抛出异常。因此,错误处理将降级为try
/ catch
,并且返回代码用于将有用数据返回给使用您的方法的客户端代码。
答案 1 :(得分:0)
我认为你的模型很合理。
声明'不控制你的程序流与异常'有点奇怪,因为这正是你应该做的事情。如果你只是继续,好像从未发生过异常,那么我无法想象你在做什么! :)
而且我也同意,你的'if'声明建议非常荒谬,任何人都应该这样做。
但是,当然,像是
try {
}
catch(SomeException e) { }
catch(Exception e){ }
合理。
- 编辑:
更新以确认我认为您的AOP没有这样做;这是非常合理的,恕我直言,无论如何。