C# 在这种情况下我应该使用异常吗?
我设计了一个简单的程序,它有一个计数器类,在这个计数器类中我有递增计数、递减计数的方法,等等。然后,我向用户展示一个菜单,让他们输入他们的选择,例如,为选项一输入1,等等。好吧,我不希望计数为负,所以为了处理这个问题,我让计数器类的SubtractCount方法在计数<0时抛出argueMetotofrangeException 然后,我让我的switch语句在异常发生时捕获该异常。我的问题是:使用异常来确保计数永远不能为负数是否不好?我应该换一种方式吗?或者更好的是,有没有更好的方法来实现这一点 代码段:C# 在这种情况下我应该使用异常吗?,c#,exception,exception-handling,C#,Exception,Exception Handling,我设计了一个简单的程序,它有一个计数器类,在这个计数器类中我有递增计数、递减计数的方法,等等。然后,我向用户展示一个菜单,让他们输入他们的选择,例如,为选项一输入1,等等。好吧,我不希望计数为负,所以为了处理这个问题,我让计数器类的SubtractCount方法在计数
static void Driver()
{
switch (userChoice)
{
case 1: // if user picks a 1, the count is deincremented
try {
myObjectOfCounterClass.SubtractCount();
}
catch (ArguemetOutOfRangeException ex)
{
console.writeLine(ex.message);
}
break;
// case 2, case 3 etc.
}
class Counter
{
private int count;
public void SubtractCount()
{
if (count < 0)
throw new ArguementOutOfRangeException("The count can never be negative!");
else
count--;
}
静态无效驱动程序()
{
开关(用户选择)
{
案例1://如果用户选择1,则计数将递减
试一试{
myObjectOfCounterClass.SubtractCount();
}
捕获(argueMetotofrangeException ex)
{
控制台写入线(例如消息);
}
打破
//案例2、案例3等。
}
班级计数器
{
私人整数计数;
公共空间计数()
{
如果(计数<0)
抛出新ArguementOutOfRangeException(“计数永远不能为负!”);
其他的
计数--;
}
异常处理可能是资源密集型的。如果为了捕获并抑制异常而计划抛出异常,则不要这样做。
相反,执行类似于从方法返回bool的操作,以向调用方指示成功
public bool SubtractCount() {
if (count < 0)
return false;
count--;
return true;
}
这就是要点
当您不想处理异常,或者无法处理异常,或者希望错误传播到您当前的编程上下文之外时,抛出异常。使用异常处理等功能很有趣,但它们可能会做得过火-我经常为在.NET framework中对感兴趣的功能执行同样的操作而感到内疚。在r控制流不被认为是良好的实践。在您的情况下,该模式更适合 您可以将计数器类更改为以下内容:
class Counter
{
private int count;
public bool CanSubtractCount
{
get { return this.count >= 0; }
}
public void SubtractCount()
{
if (!this.CanSubtractCount)
throw new InvalidOperationException("The count can never be negative!");
else
this.count--;
}
static void Driver()
{
switch (userChoice)
{
case 1: // if user picks a 1, the count is deincremented
if(myObjectOfCounterClass.CanSubtractCount)
{
myObjectOfCounterClass.SubtractCount();
}
else
{
// Write a message to the user?
}
break;
// case 2, case 3 etc.
}
}
现在,您可以像这样重写客户端:
class Counter
{
private int count;
public bool CanSubtractCount
{
get { return this.count >= 0; }
}
public void SubtractCount()
{
if (!this.CanSubtractCount)
throw new InvalidOperationException("The count can never be negative!");
else
this.count--;
}
static void Driver()
{
switch (userChoice)
{
case 1: // if user picks a 1, the count is deincremented
if(myObjectOfCounterClass.CanSubtractCount)
{
myObjectOfCounterClass.SubtractCount();
}
else
{
// Write a message to the user?
}
break;
// case 2, case 3 etc.
}
}
实际上,计数<0时的情况似乎不是“异常”。使用正常的“如果”,则不需要异常。当您可以使用流控制时,您不应该将异常用于流控制。您可以检查是否小于零,或者(a)不对其采取行动,或者(b)显示消息,或者(c)把东西关在正确的地方
除了这个例外,你基本上把所有的东西都扔到地板上,就好像发生了一场大灾难,这时可以更优雅地处理它,甚至发出警告并继续。我认为如果值已经为零,在SubtractCount()方法中抛出一个异常是可以的 顺便说一句,如果(计数<0)不是
if(计数==0)
但是,如果减法计数已经为零,我会让UI阻止用户选择减法计数,从而首先避免了异常情况
顺便说一句-不要引发ArgumentOutOfRangeException。当传递给方法的参数不在可接受的范围内时,应使用此选项。您的方法不接受任何参数。更合适的异常类型是InvalidOperationException。首先,您应该确保计数器实际上不能为负。C当前,它将递减为-1,如果您尝试将其递减为-2,则抛出异常 作为捕获异常的替代方法,您可以将检查公开为
CanDecrement
属性,以便单独使用:
class Counter {
private int count;
public bool CanDecrement { get{ return count > 0; } }
public void Decrement() {
if (!CanDecrement) {
throw new ArguementOutOfRangeException("The count can never be negative!");
}
count--;
}
}
用法:
if (myObjectOfCounterClass.CanDecrement) {
myObjectOfCounterClass.Decrement();
} else {
Console.WriteLine("The count can not be negative.");
}
通过这种方式,您可以在预期条件发生的代码中使用属性,而在通常情况下不应该发生的代码中,您可以调用
递减
,并让异常像任何其他意外错误一样进行处理。异常只应在异常情况下使用,用户在递减时再单击一次按钮也不例外。您可以通过简单的控制逻辑来处理它。如果计数器为零,您就不能减少计数器。此外,您应该更改UI。如果计数器为零,用户应该阻止减少选项,这样用户就永远不会有进一步减少计数器的选项。这不是一个非常清晰的API设计。如果返回值为false?它还违反了命令/查询分离。我认为如果该方法名为TrySubtractCount,那么它将非常清楚!至于正确的体系结构,我更喜欢@Mark Seemanns的答案-不,count不能为负,但可以为零。我理解。这意味着您需要测试SubtractCount()的情况正在调用,并且计数已经为零,即如果(计数==0)throw exception一个很好的答案,但重要的一点是ArgumentOutOfRangeException不应该被抛出,我宁愿推荐InvalidOperationException或从中派生出来的东西。@AdamRalph:Agreed-InvalidOperationException是正确的抛出异常类型。编辑了我的答案:)我想我甚至不需要抛出exception,只需要为返回bool:public bool CanSubtractCount(){if(count))的计数器类创建一个方法,我的目标是确保当最终用户打开菜单时,如果选中会导致错误的菜单项将被禁用或不可用“在关口阻止他们”设计模式:)