【问题标题】:Confusion about throw and assert关于 throw 和 assert 的混淆
【发布时间】:2012-06-15 11:15:41
【问题描述】:

这是我第一次编写库(供我在多个游戏中使用),所以我认为为了良好的编程习惯,我应该彻底注释我的代码,添加 XML 摘要并在用户完成此库时使用异常处理许多 .NET 类中的问题(用户可能是我或我的队友)

这是 NoteRow 类的构造函数(顺便说一句,我正在开发音乐游戏),它需要在创建时确定数组的大小

bool[] l1NoteData;
public NoteRow(int numberOfNotes)
{
     this.l1NoteData = new bool[numberOfNotes];
}

现在我有了这个方法来切换 l1NoteData 数组上的布尔值。

public void toggleNote(uint index)
{
     l1NoteData[index] = !l1NoteData[index]
}

因此,作为防御性编程,我想检查索引(该类的用户将指定,即我或我的队友)是否超出了创建此类时指定的范围。

我已经阅读了很多 throw exception vs. assert vs. return bool 等,但仍然感到困惑,无法选择。这是我的担忧:

  • 我是否应该使用 'if' 语句来检查索引是否超过 l1NoteData.length,然后在超出时触发异常,因为知道在使用 'out of range' 索引执行该行时无论如何都会触发异常? (IndexOutOfRangeException) 如果是这样,那么抛出异常有什么用?如果出现问题,无论如何都会有默认异常?
  • 我读过 Assert 是为程序员准备的。通知程序员代码不像程序员假设那样工作。与抛出异常(由用户处理异常测试用例)相比,人们永远无法注入测试用例来使断言触发(如果它被触发则代码错误)。现在这个图书馆的用户将是我。所以我被认为是程序员或用户?我,作为这个类的用户,可能会调用toggleNote 并且输入索引超出数组的限制,所以会抛出异常。或者我,作为我的游戏的程序员(这个库是我的游戏的一部分)应该把 assert 放在那里,这样我就不会错误地用超限索引调用 toggleNote从我的游戏。 (使用这个库)我现在可以知道游戏的代码是错误的,因为 assert 被触发然后修复它并最终进入发布版本。 (然后断言代码将消失)
  • 从上面的问题来看,如果我彻底测试,我确定没有更多的错误导致断言运行,然后进入发布版本。我知道断言不会在发布版本的代码中......但这真的很好吗?程序中可能还存在更多错误,因此现在当用户遇到该错误时,断言不再用于捕获错误。所以当我可以使用异常并且如果用户导致该异常触发时,断言真的很好用,我作为开发人员可以收到该错误报告来修复它等(但用户是我和我的朋友)
  • 抛出异常比返回 bool 表示成功/失败要好 100%?您认为哪个示例更适合返回 bool?

抱歉我的英语混乱,因为我已经对这个问题感到困惑......

【问题讨论】:

    标签: c# exception assert throw


    【解决方案1】:

    断言仅用于测试。断言不用于生产应用程序中的错误处理

    您应该预先检查(如果)输入是否来自用户、预期错误等。

    如果一个错误完全出乎意料,那么这就是异常处理的目的。

    如果你自己的程序提供了 index 参数,那么如果传递了错误的值就是一个 bug。例外情况很好。

    关于这个问题已经提出了几个很好的问题

    Are exceptions really for exceptional errors?

    Debug.Assert vs Exceptions

    Exceptions vs "if" in C#

    【讨论】:

      【解决方案2】:

      问自己一个简单的问题:你想阻止它发生吗?

      如果是,检查方法入口的索引,如果无效则抛出异常。这是在方法调用中验证参数的常用方式。

      如果不是,那么您有一些选择。

      • 可以使用System.Diagnostics.DebugSystem.Diagnostics.Trace记录无效索引,静默返回,不做任何操作。
      • 你可以忽略它,它无论如何都会抛出一个IndexOutOfBoundsException
      • 您可以防止它停止异常,否则从方法中正常返回。

      【讨论】:

        【解决方案3】:

        使用预检查(函数顶部的简单 if 语句)抛出自己的异常的最大原因是您可以指定自己的非常详细的异常消息。您可以明确地说“嘿,笨蛋。您试图切换一个不存在的音符”,而不是默认的“索引超出数组边界”或其他任何内容。或者任何你想要的。

        您自己的例外情况的另一种情况是那些浏览您的库代码的人。您明确检查错误,任何浏览您的库源的人都会收到警告,这是一个潜在的错误。在代码中明确说明您想要做什么。

        【讨论】:

          【解决方案4】:

          首先。通常说,返回码之前的异常的一个好处是异常不能被忽略。这为您提供了用例。如果您不希望使用您的库的用户(程序员)错过重要的事情,请使用例外。 第二。我认为,无论是作为程序员还是作为用户,您都不应该在库中的一般情况下使用断言。我的意思是你应该在使用你的库的代码中使用断言来检查你的假设是否正确。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-04-11
            • 2017-09-12
            • 2016-04-24
            • 1970-01-01
            • 2013-07-07
            • 2015-10-30
            • 2013-10-21
            • 2014-12-31
            相关资源
            最近更新 更多