关于throw和断言的困惑

时间:2012-06-12 14:37:52

标签: c# exception assert throw

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

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

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

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

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

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

我已经阅读了很多抛出异常与断言与返回布尔等等,但仍然困惑,无法选择。这是我的担忧:

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

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

4 个答案:

答案 0 :(得分:2)

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

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

如果错误完全出乎意料,那就是异常处理。

如果您自己的程序提供索引参数,那么如果传递了错误的值则是一个错误。例外情况适用于此。

有人提出了几个好问题

Are exceptions really for exceptional errors?

Debug.Assert vs Exceptions

Exceptions vs "if" in C#

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

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

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

  • 您可以使用System.Diagnostics.DebugSystem.Diagnostics.Trace来记录无效索引,并在不执行任何操作的情况下静默返回。
  • 您可以忽略它,无论如何都会抛出IndexOutOfBoundsException
  • 你可以防止它停止异常,但是否则从方法正常返回。