自定义异常的成本

4

我读到过抛出异常是一项昂贵的操作。然而,创建自己的异常是否会使您的代码更具表现力和可读性呢?

我的一些同事建议使用System.Exception并将自定义文本插入消息中,而不是创建新的自定义异常。

我对其他意见很感兴趣。欢迎任何建议。


2
嗯,抛出异常和定义自己的异常类有什么关系呢?无论您使用 System.Exception 还是从它派生或使用其他内置类,您都必须抛出它,因此费用实际上在于生成和抛出异常,而不是编写它们。 - BoltClock
2
你的同事在开玩笑,如果不是这样的话,希望他不会再成为你的同事太久。 - Rex M
1
除非他们的意思是编写自定义类然后将其丢弃比从一开始就使用内置类花费更多的人工时间。如果是这样的话...哈哈。 - BoltClock
8个回答

4
永远不要抛出System.Exception。问题在于调用代码。捕获通用的Exception对象是一种不好的做法,原因有很多。如果你抛出Exception基类的实例,那么调用代码别无选择,只能捕获Exception,如果他们想处理它。这强制调用代码使用不良的做法。此外,如果调用代码只得到异常的Exception,那么没有可靠的方式来区分异常是什么。通常最好使用其中任何一个预定义的异常(ArgumentException、InvalidOperationException等)。如果没有正确描述情况的异常,则自定义异常类是一个完全可行的方法。

1
在没有其他合理的操作(除了记录异常)并且手头没有适当的BCL异常的情况下(虽然这很少见),抛出“Exception”比创建否则毫无意义的自定义异常更好。 - Jeff Sternal
2
只是出于好奇,你是否曾经编写过捕获 ArgumentException 的代码? - StriplingWarrior
@Jeff Sternal - 在这种情况下,抛出一个 ApplicationException 更为合适。 - Jeffrey L Whitledge
1
@Jeffrey - 我并不认为这会增加任何价值,就像微软不再建议从ApplicationException派生自定义异常一样(“最初认为自定义异常应该从ApplicationException类派生; 然而,在实践中发现这并没有增加显著的价值。有关更多信息,请参阅处理异常的最佳实践。”) - Jeff Sternal
@Jeffrey L Whitledge:既然你不抛出“Exception”的唯一原因是为了让人们可以单独捕获你的异常,那么抛出“ArgumentException”有什么优势呢?我只是觉得这里给出的理由不足以支持你所倡导的强硬立场。(编辑:我并不是说你永远不应该抛出“ArgumentException”——我只是认为从来不抛出“Exception”可能有点过头了。) - StriplingWarrior
显示剩余5条评论

2

抛出异常本身的开销(创建对象、遍历堆栈等)是很高的。自己制作异常类几乎不会增加任何开销,因此,如果要抛出异常,请不要使用new Exception("message")


1

异常并不是给人类阅读的(尽管人们会阅读它们的信息和堆栈跟踪),而是给代码阅读的。如果您的代码能够对自定义异常做出响应,那么请务必这样做。但是,异常只是注定要被记录下来,没有必要创建自定义异常。

自定义异常的开销在于需要维护和测试另外一组内容。如果已有的异常适用,就使用它们。(例如,使用ArgumentNullException而不是ZipCodeNullException。)


1
  1. 如果有任何理由使您的异常与标准异常不同地被捕获和处理,那么您应该创建自己的类。
  2. 如果有任何理由使您的异常接受不同的参数(例如,基于一组常见参数生成特殊格式的消息),那么您应该创建自己的类。

在任何其他情况下,只需使用 Exception 即可。一般来说,实例化或抛出自定义异常并不比标准异常更耗费资源,至少与首次抛出异常的开销相比如此。异常本质上应该是异常的,因此在抛出异常时性能不是问题。关键是在查看为什么抛出异常时拥有所有所需信息。


0

你的同事在胡说八道。无论是哪个类,抛出异常的成本都是相同的。

说实话,“昂贵”的异常 - 是的,它们比空检查或其他一些操作更昂贵,因此永远不要将它们用作某些理智检查的替代品,但应该在它们有意义的地方鼓励使用(例如 IOException,这是它们的一个很好的用例 - I/O 问题是一个特殊情况,通常必须在正常程序流之外处理)。


实例化一个异常并不特别耗费资源;但是抛出它会消耗更多的资源。 - Gabe
无论是定制还是非定制,抛出操作都不会增加成本 - 抛出操作与类型无关。 - sksamuel

0

你不应该抛出 System.Exception,因为唯一能捕获它的方式是通过 catch(System.Exception)。这样做非常不好的习惯,应该捕获特定的异常,这样可以在不崩溃软件的情况下正确处理它们。通过生成自定义异常,您可以识别并从中恢复。

例如,如果您的代码意味着要打开一个文件,但出现了未知异常,那么该如何恢复?然而,如果您捕获了特定的“文件未找到”异常,那么恢复就容易得多了。您可以明确告诉用户该文件不存在。

我认为自定义异常并不比内置异常更昂贵。


0
“昂贵”是一个相对的术语,正如其名称所暗示的那样,异常应该是一个例外,因此它可能不会影响您代码的性能。据我所知,抛出异常的成本与异常类型无关,因此您不应该限制自己只使用System.Exception。
但最重要的是:http://c2.com/cgi/wiki?PrematureOptimization

0

我更喜欢使用最合适的内置异常,如果不存在,则从System.ApplicationException派生自己的异常。

我不建议抛出带有自定义消息的System.Exception。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接