什么更好:int.TryParse还是try { int.Parse() } catch?

66

我知道..我知道...在这里性能不是主要关注点,但只是出于好奇,哪个更好?

bool parsed = int.TryParse(string, out num);
if (parsed)
...

或者

try {
    int.Parse(string);
}
catch () {
    do something...
}
9个回答

97

更好是高度主观的。例如,我个人更喜欢使用 int.TryParse,因为大多数情况下,如果解析失败,我通常不关心为什么会失败。 然而,int.Parse 可以(根据文档)抛出三种不同的异常:

  • 输入值为空
  • 输入值格式无效
  • 输入值包含导致溢出的数字

如果你在乎解析失败的原因,那么显然应该选择 int.Parse

一如既往,上下文至关重要。


2
虽然我同意上下文是至关重要的,但我认为TryParse几乎总是更好的选择,它不仅仅是高度主观的个人偏好。你的反例(区分可能抛出的不同异常)相当罕见,并且可能最好使用每种异常类型的catch块来编码,而不是使用catch all。 - Joe
2
@Joe:是的,如果你想区分不同的异常类型,除了特定的catch块之外的任何其他方法都会显得非常奇怪。我的回答旨在讨论ParseTryParse之间的区别,而不是问题中的具体代码示例。正如我在评论中提到的那样,我同意TryParse几乎总是更好的选择,但关键词是“几乎”,而不是“总是”。 - Fredrik Mörk
@Joe:我已经提出了那个论点。请参见原问题的评论交流。Fredrik关于绝对陈述从来不是真实的说法是正确的。(天哪,一个悖论!) - Cody Gray
万岁,国王陛下。 - MrBoJangles

44

转换有时失败是异常的,还是预期和正常的?如果是前者,请使用异常。如果是后者,则避免使用异常。异常被称为“异常”,这是有原因的;您应该仅在处理异常情况时使用它们。


1
我喜欢这个解释,因为我解析了很多用户数据,无论是否预期失败(以及发生故障时该怎么做)都会影响整个项目。 - JYelton
Eric,我很想听听你对http://www.boost.org/community/error_handling.html的看法:““这是一个异常(或意外)情况吗?”这个准则听起来很有吸引力,但通常是错误的... 更恰当的问题是:“我们想要堆栈展开吗?” - Jon
@Jon:我想到了几件事情。首先,你不能反驳这个重言式,即在你想要异常行为的情况下,异常是正确的,但你也无法从中学到任何东西。其次,“异常”和“意外”是两回事。第三,谁说堆栈展开与此有关?这是 C# 的实现细节。在异步方法中抛出的异常不会展开堆栈;堆栈早已消失。它们向任务发出信号,表明发生了异常事件。不要混淆语义和实现。 - Eric Lippert
我同意boost指南提出了一个问题:“我们何时需要堆栈展开?”但是这句话也很有道理:“问题在于一个人的‘异常’可能是另一个人的‘预期’”。解析失败算不算异常?到达文件结尾算不算异常?我们如何客观地确定这一点呢? - Jon

25
如果确实预计有时转换会失败,我喜欢使用int.TryParse,并将其与条件(三元)运算符整齐地放在一行上,就像这样:
int myInt = int.TryParse(myString, out myInt) ? myInt : 0;

如果TryParse方法失败,将使用零作为默认值。对于可空类型非常有用,如果转换失败,它将覆盖任何默认值并替换为null。

1
这与以下代码是完全等价的:int myInt; int.TryParse(myString, out myInt);。如果失败,TryParse() 已将结果设为 0。 - user645280
3
正确,但使用我的版本,您可以指定一个替代的默认值,例如10 - greg84

11

第一种是常规编码方式。第二种被视为按异常情况进行编码


8

就我个人而言,我更喜欢:

if (int.TryParse(string, out num))
{
   ...
} 

4
第一点!你不应该通过异常来编码。
你可以简化为: if (int.TryParse(string, out num))

4

首先,远远地说。正如乔治所说,第二个是通过异常编码,对性能有重大影响。而性能应该始终是一个关注点。


2
捕获异常会增加更多的开销,所以我会选择使用 TryParse。
此外,TryParse方法在转换失败时不会抛出异常。它消除了使用异常处理来测试格式异常的需要,如果s无效且不能成功解析,则可以避免这种情况。
最后一部分从这里复制粘贴过来的。

2

需要记住的另一件事是,异常可以(可选地)记录在Visual Studio调试/输出窗口中。即使异常的性能开销可能微不足道,但在调试时为每个异常编写一行文本可能会使事情变得非常缓慢。更值得注意的异常可能会淹没在所有失败的整数解析操作的噪音中。


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