1

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

对不起,我的英语令人困惑,因为我已经对这个问题感到困惑......

4

4 回答 4

2

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

您应该预先检查(如果)输入是否来自用户,是否会出现错误等。

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

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

对此提出了几个很好的问题

异常真的是异常错误吗?

Debug.Assert 与异常

C# 中的异常与“如果”

于 2012-06-12T14:41:19.340 回答
2

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

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

于 2012-06-12T14:44:25.280 回答
2

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

于 2012-06-12T14:44:50.100 回答
1

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

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

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

  • 您可以使用System.Diagnostics.DebugorSystem.Diagnostics.Trace记录无效的索引,然后静默返回,无需执行任何操作。
  • 你可以忽略它,它IndexOutOfBoundsException无论如何都会抛出一个。
  • 您可以防止它停止异常,否则从方法中正常返回。
于 2012-06-12T14:43:41.023 回答