2010-06-03 47 views
4

有一次,我读的是MSDN article鼓励下面的编程范式(它不是100%真实......看到编辑):抛出异常:封装它们还是不封装?

public class MyClass 
{ 
    public void Method1() 
    { 
     NewCustomException(); 
    } 

    public void Method2() 
    { 
     NewCustomException(); 
    } 

    void NewCustomException() 
    { 
     throw new CustomException("Exception message"); 
    } 
} 

你觉得这种模式是有意义的?将异常消息存储在static const字段中,然后将它传递给异常的构造函数是不够的,而不是封装整个异常抛出?

编辑:

使用异常生成器方法。它是 常见的一类,在其 执行中抛出异常来自不同地方的 异常。为避免过多的代码,请使用助手方法,该方法会创建异常并将其返回。

我只注意到(见引用),该文章讲述到回报异常:

public class MyClass 
{ 
    public void Method1() 
    { 
     throw NewCustomException(); 
    } 

    public void Method2() 
    { 
     throw NewCustomException(); 
    } 

    CustomException NewCustomException() 
    { 
     return new CustomException("Exception message"); 
    } 
} 

你觉得这个怎么样?

+0

如果您打算为其添加额外的逻辑,您需要在其他地方添加额外的逻辑,封装异常抛出是非常好的。 – 2010-06-03 16:35:53

+0

好的。但我的意思只是抛出异常,没有任何逻辑。 – Simon 2010-06-03 16:37:36

+0

你有链接到这篇文章的机会吗?阅读某人推荐的背景是很好的。 – 2010-06-03 16:39:02

回答

10

我的理解是,传递一个异常实例是一种失算,如果没有其他原因,你会失去与异常相关的堆栈跟踪。调用另一个方法会改变堆栈跟踪,从而使其无效。我建议至少让堆栈跟踪异常并将它作为参数传递给一些帮助者,如果这是你要走下坡路的话。

+0

他不是在传递一个异常实例,只是把它的消息放在'const'中。 – 2010-06-03 16:37:33

4

这是我的书中的一个重构。您必须在堆栈跟踪中返回一行以准确查看发生问题的位置。如果您的自定义例外总是使用相同的消息,请将其放在CustomException类中。如果在你引用的代码中只有相同的内容,那么是的,把它放在const字段中(你不能有static const - 它隐含地为static)。

+0

Infact你不能把一个异常放入'const'字段中。 '静态只读'是最接近你可以得到的。 – 2010-06-03 16:36:33

+2

@Matti:他不是在谈论这个异常,只是它的错误信息。 – 2010-06-03 16:37:07

+1

哦。如果我正确地阅读东西,我想这会有所帮助¬__¬ – 2010-06-03 16:40:53

0

我没有看到制作一个简单地引发异常的方法。但是,我认为放弃自定义异常有价值。如果您抛出的所有异常都是自定义异常的子节点,它可以让您快速查看抛出的异常是否是您正在处理的异常或尚未处理的异常。此外,你可以赶上MyBaseException,它不像捕捉Exception差。

0

如果你不知道你打算如何处理异常,那么这么做很方便。你想扔掉它吗?或者也许以后你会在某个地方记录这个异常然后扔掉它?或者可能传递一些与异常绑定的参数(即方法名称等)?

在这种情况下,创建一个处理异常情况的单独方法在您想要更改时很方便。

我通常不会为此感到困扰 - 相反,只是预先确定如何处理异常(即您要放置消息的字符串信息)。

2

我会建立一个Exception,而不是抛出它的方法。如下面的示例。我似乎记得看到一个微软的指导方针,建议这个,但我不记得在哪里。

利用这种技术,如果你想改变任何原因的异常类型,你只需要在一个地方这样做(例如,从ConfigurationExceptionConfigurationErrorsException从.NET 1.x的升级时更改.NET 2.0) 。

此外,您还尊重DRY原则,方法是让代码的单个副本与其消息以及异常中包含的任何其他数据一起构建异常。

你显然不会在琐碎的情况下做到这一点(例如,你将不会取代由throw BuildArgumentNullException("myParamName")throw new ArgumentNullException("myParamName")

private static Exception BuildSomeException(... parameters with info to include in the exception ...) 
{ 
    string message = String.Format(...); 
    return new SomeException(message, ...); 
} 

... 
throw BuildSomeException(...); 
3

还有一个问题,你得到这样做是会有很多的地方,你甚至不会能够抛出异常,因为编译器不会允许它。考虑添加到您的类这两种方法:

public string GetFoo1(bool bar) 
    { 
     if (bar) 
      return ""; 
     else 
      NewCustomException(); 
    } 

    public string GetFoo2(bool bar) 
    { 
     if (bar) 
      return ""; 
     else 
      throw new CustomException("Exception message"); 
    } 

GetFoo1将无法编译,而GetFoo2会。

+1

+1好的一点是,如果封装在方法中,编译器不会看到这个throw。 – Joe 2010-06-03 16:56:45

0

我一般比较喜欢存储异常消息资源。这有以下几个目的:

  • 如果要求归结为本地化异常消息,这是一件容易的事。
  • 异常消息往往在整个开发人员中更加标准化,因为额外的工作是创建一个新的但仅稍微不同的消息。
  • 如果您确保消息被标识符引用,并且在引发时包含该标识符和异常,那么将消息跟踪到抛出它的代码会更容易。

缺点是它只是比硬编码消息需要更多的努力。