RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 558472
Accepted
iluxa1810
iluxa1810
Asked:2020-08-23 18:56:13 +0000 UTC2020-08-23 18:56:13 +0000 UTC 2020-08-23 18:56:13 +0000 UTC

哪个更正确使用:if () 或 try-catch?

  • 772

例如,当你需要在表中创建一个列,但表中没有这样的列时,使用什么?

我可以,如何编写代码来检查列是否存在,然后才添加它而不会出错,所以我可以尝试添加列而不检查,将方法包装在try-catch( если есть-将捕获异常;если нет-该列将被添加)。

工作的结果将是相同的。

还有很多这样的例子,比如你可以检查文件是否存在,然后才复制,或者你可以捕获异常。

哪种方法更有效或更正确?

исключения
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Mark Shevchenko
    2020-08-29T23:34:15Z2020-08-29T23:34:15Z

    异常可以让您的代码更清晰、更易于理解,因为它们可用于将操作的执行与错误处理分开。Martin 的书“Clean Code”首先描述了这方面。

    同时,以我的经验,分离代码是很有必要的:在单独的方法中取出try/块。catch处理你的程序的程序员会说“谢谢”。这种构造非常笨重,即使是try/的简单形式finally,而且在大型方法的中间会让任何人感到困惑。

    异常的第二个优点是它们允许您传递附加信息。atoiC 函数无法说明它无法将字符串转换为整数的确切原因。

    int result;
    result = atoi("123"); /* в result 123 */
    . . .
    result = atoi("foo"); /* что в result? */
    

    在 Java 和 C# 等语言中,您可以通过将一些错误代码与调用上下文等结合起来,为您的异常类添加必要的属性。例子:

    . . .
    catch (SqlException e)
    {
        Console.WriteLine("Ошибка '{2}' в строке {0} процедуры {1}", e.LineNumber, e.Procedure, e.Message);
    }
    . . .
    

    长期以来坚定地转向异常的开发人员通过不返回任何错误代码,特别是臭名昭著的null ,使他们的代码更加清晰:

    // Что будет, если в хранилище нет пользователя с указанным userid?
    // Вернёт null или сгенерирует исключение?
    User user = userRepository.GetById(userId);
    

    目前,认为抛出异常更为正确(关于论据,我再次参考《代码整洁之道》一书)。如果该方法用于检查用户是否存在,建议将其转换为表单TryX。它很笨拙,但很熟悉,至少对 .NET 程序员来说是这样:

    User user;
    if (userRepository.TryGetById(userId, out user))
    {
        . . .
    }
    

    更有价值的是,它是明确的:看代码,你不会想:“如果没有这样的用户怎么办?”

    现在让我们从另一面看一下情况——什么时候不应该使用异常?在我看来,当它们使代码难以理解时。如果情况没有异常,那么在程序文本中应该有一个正常的检查。

    例如,新文档的应用程序生成名称Untitled.foo、Untitled1.foo、Untitled2.foo等。

    已经存在同名文件的情况很常见,并非例外,因此使用通常的检查来实现代码更正确:

    public string GetNewDocumentName(string prefix)
    {
        var filename = prefix + ".foo";
    
        if (!File.Exists(filename))
            return filename;
    
        int suffix = 0;
        do
        {
          filename = prefix + (++suffix).ToString() + ".foo";
        } while (File.Exists(filename));
    
        return filename;
    }
    

    这段代码不仅比使用异常的类似代码更快,更重要的是,它更容易被其他程序员理解,因为它隐含地向他们传达了额外的信息:这件事会定期发生,我们已经做好了准备。

    但是,例如,一个文件夹中累积了 20 亿个无标题文件的令人难以置信的情况无疑是一个例外。

    public string GetNewDocumentName(string prefix)
    {
        var filename = prefix + ".foo";
    
        if (!File.Exists(filename))
            return filename;
    
        int suffix = 0;
        do
        {
          if (suffix == int.MaxValue)
                throw new InvalidOperationException("You're crazy!");
    
          filename = prefix + (++suffix).ToString() + ".foo";
        } while (File.Exists(filename));
    
        return filename;
    }
    

    这段代码看起来比较混乱。幸运的是,我们可以将部分检查分配给 C# 编译器:

    public string GetNewDocumentName(string prefix)
    {
        var filename = prefix + ".foo";
    
        if (!File.Exists(filename))
            return filename;
    
        int suffix = 0;
        do checked
        {
          filename = prefix + (suffix++).ToString() + ".foo";
        } while (File.Exists(filename));
    
        return filename;
    }
    

    另一个规则从何而来:如果您了解语言、平台、库并依赖它们的异常,代码可以变得更清晰。

    我在上面写过异常比检查慢,我想澄清我的观点:做决定时不要依赖性能。正确的意义传递给另一个程序员,代码的纯度才是自己应该追求的。性能差异虽然存在,但从来没有大到足以让用户注意到。好吧,除非您在某些图形引擎中为嵌套循环本身编写代码。

    • 49
  2. Pavel Mayorov
    2020-08-23T19:35:56Z2020-08-23T19:35:56Z

    预检查速度更快,而且通常更准确。但只有异常处理才能提供充分的保证。

    示例:简单的文件创建。这里的错误是可能的 - 大海:

    • 名称可能包含禁止使用的字符(允许的字符集取决于文件系统!);
    • 文件的完整路径可能太长;
    • 该文件可能已经创建;
    • 可能无权创建文件;
    • 光盘可能有写保护或根本没有写保护(CD-ROM 就是一个例子)。

    所有这些选项都可以提前检查 - 并用俄语向用户提供明确的信息。

    但是有一些情况是没有预检会抓到的:

    • 该文件可以在验证后立即由另一个程序创建;
    • 该文件可能被防病毒软件阻止;
    • 如果文件是在网络资源上创建的,则网络可能会“掉线”。
    • 31

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5