请示还是道歉?

14 投票
5 回答
1219 浏览
提问于 2025-04-16 19:18

我之前是学Python的,听说过一句话:有时候道歉比请求许可更简单。具体来说,下面这两个代码片段:

if type(A) == int:
  do_something(A)
else:
  do_something(int(A))

try:
  do_something(A)
except TypeError:
  do_something(int(A))

在大多数情况下,当A通常是一个整数时,第二种方式会更快(假设do_something需要一个整数作为输入,并且会很快抛出异常),因为你在每次执行循环中省去了逻辑测试,虽然这样可能会导致更昂贵的异常,但发生的频率却少得多。

我想确认的是,这在C#中是否也成立,或者说逻辑测试的速度是否足够快,相比于异常处理,这种情况是否算是个小问题?

哦,我只关心发布版本的性能,不考虑调试版本。


好吧,我的例子太模糊了,试试这个:

简单的解决方案:

return float(A) % 20 # coerse A to a float so it'll only fail if we actually don't
                     # have anything that can be represented as a real number.

基于逻辑的解决方案:

if isinstance(A, Number): # This is cheaper because we're not creating a new
    return A % 20         # object unless we really have to.
else:
    return float(A) %20

基于异常的解决方案:

try: # Now we're doing any logical tests in the 99% of cases where A is a number
  return A % 20
except TypeError:
  return float(A) % 20

使用文件系统对象、数据库连接或网络相关的东西的例子会更好,但对于这个问题来说有点长。

5 个回答

6

一般来说,我认为不应该用异常来控制程序的流程。异常应该用在特殊情况下——比如如果你确实期望A是一个整数,那么你最开始的做法是合理的。如果A可能是整数也可能是字符串,那么第二种方法更容易让人看懂。

从性能上来说,在发布版本中是有区别的——合理的逻辑判断肯定是足够快的——所以我个人会选择可读性更高的方式。

8

.NET中的异常处理比较复杂,所以在C#中,通常只在特殊情况下才使用异常,而不是用它来控制程序的正常运行。

在C#的设计理念中,还强调在使用外部代码传来的输入之前,应该先检查这些输入是否正确。举个例子:

public void Foo(int i)
{
    if (i == 0)           // validate input received from external code
    {
        throw new ArgumentOutOfRangeException("i");
    }

    DoSomething(i);
}

public void Foo()
{
    DoSomething(1);
}

internal void DoSomething(int i)
{
    Debug.Assert(i != 0); // validate that i is not zero in DEBUG build
                          // assume that i is not zero in RELEASE build

    Console.WriteLine(42 / i);
}
17

可能不是这样。 .NET中的异常处理相对来说是比较耗费资源的。

因此,有几个.NET函数提供了两种选择。(比如int.TryParse,它返回一个成功的代码,通常被推荐使用,因为它比int.Parse快,后者在失败时会抛出异常)

但最重要的答案是你自己测量的数据告诉你什么。如果你需要性能,那就要不断地测量、测量、再测量。

因为在的电脑上,使用我的代码,配合的.NET框架版本,在这个时间点上最快的方式,可能在你的电脑上,使用你的代码,配合你当时阅读时的.NET框架版本,就不一定是最快的了。

撰写回答