try/catch 性能优化

3
我需要读取不同类型的 .txt 文件,为此我首先读取标题所在的前几行。有了这些信息,我就能选择正确的读取方式。问题是,如果只有一个记录以不同格式存在(比如我使用了 substring(0,45),但是只有40个字符),我的应用程序就会崩溃。我想避免这种情况,但是我不能检查每一种可能性。我已经阅读过了应该避免使用太多 try/catch 的建议,我只在我不知道错误来源的情况下使用它。

我的问题是:在循环中使用 try/catch 是不好的吗?(30k - 40k 次)?

如果不是,我该如何正确使用它?我不完全理解异常的目的。它们仅用于调试吗?如果不是,throw new exceptionMessageBox.Show("Error") 之间有什么区别?

如果我不通知错误而只是跳过它,我可以写类似以下内容的代码:

try
{
//problematic code
}
catch
{
//nothing
//continue;
}

你为什么想要避免这个?这个文件是有问题的,不是你想忽略的东西。如果你捕获并吞噬异常,那么你只是写了一个忽略坏数据的程序,很可能会产生坏数据。而且没有任何方法让用户找出问题所在。 - Hans Passant
是的,你说得对。我在考虑其他情况使用那个片段。感谢建议。附注:如果用户选择了一个损坏的文件并且我抛出了30k个异常,我该怎么办? - Sturm
3个回答

3
在循环中使用try/catch(30k-40k次)是不好的吗?
只有在预期会出现大量异常时才会影响性能。如果没有抛出异常,那么性能开销就很小。
它们不仅用于调试,而且主要用于在运行时查找错误(通常会记录异常,以便您可以查看程序崩溃的位置/原因)。您无法预料所有情况,因此设置一个日志,一旦程序崩溃,您就可以进行咨询,这非常有帮助。
它们还允许恢复(如果您知道导致异常的原因并知道如何处理它)。其中一个例子是数据库事务死锁-当两个线程竞争相同的数据库资源时,将选择终止一个(死锁受害者)-这只能通过异常捕获并通过重试事务来处理。
以下内容存在巨大问题:
catch
{
//nothing
}

为什么?因为你可能会忽略未预料到的异常——你将它们扔掉,而当程序最终崩溃或出现奇怪的错误时,你将一无所知。

我忘了在那个catch中加上退出循环的语句。由于我将读取的列表存储在最后,所以我会得到一个空文件,我已经确保这不会引起问题。这不正确吗? - Sturm
@Sturm - 我不知道。这真的取决于您的应用程序所需的逻辑。 - Oded

3

但是我无法检查每种可能性。

其实,你可以!这通常是这样完成的。在工程一个复杂的函数时,您希望考虑到每种情况。每个没有考虑到的情况都有可能成为潜在的错误。

而你的try-catch语句正在隐藏你没有考虑到的错误。你需要让异常继续往上抛出,这样你才能注意到它们并解决底层问题。

严格遵守所有空引用和索引越界异常都是真正的错误的约定。这将节省您最终的时间。


一个好的工程师的标志之一是不引入多余的情况。例如,如果您不需要可空值类型,请仅使用值类型,这样可以消除不必要的复杂性,并减少需要验证的场景。工程师经常思考和辩论正确的抽象程度。判断进一步抽象是否是正确选择的最佳方法是回答两个问题:1.它是否满足要求?2.进一步抽象是否增加了必须处理的情况数量? - N-ate

2
从性能角度来看,在 try-catch 块中运行代码与不在其中运行相比,会有微小的性能损失。请查看 Do try/catch blocks hurt performance when exceptions are not thrown? 以了解差异的实证证据。 throw new exceptionMessageBox.Show("Error") 之间有什么区别?
首先,异常是一个可以保存信息并被扩展以创建自定义异常的对象,而 MessageBox.Show() 只使用文本向用户显示信息。简而言之,一个是对象,另一个是向用户显示信息的机制。它们不应被视为竞争选择,而应被视为互补选择。
最后,catch { //nothing } 是一个可怕的想法,它相当于把头埋进沙子里,以避免听到坏消息。永远不要这样做!

1
“Tiny”在这里的意思是“几乎可以忽略不计”。根据其他答案,他们测量出的开销不到单次调用Math.Sin成本的15%(虽然它不如整数乘法快,但肯定比像OP在这里使用的Substring调用要快得多)。在OP的用法中,开销可能甚至无法被测量,更别说对用户有所察觉了。 - Sam Harwell
所以像反射这样的东西不要放在高流量区域,但与反射不同的是,在高流量区域使用它不会破坏你的性能。 :) - N-ate

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