Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在这种情况下我应该使用异常吗?_C#_Exception_Exception Handling - Fatal编程技术网

C# 在这种情况下我应该使用异常吗?

C# 在这种情况下我应该使用异常吗?,c#,exception,exception-handling,C#,Exception,Exception Handling,我设计了一个简单的程序,它有一个计数器类,在这个计数器类中我有递增计数、递减计数的方法,等等。然后,我向用户展示一个菜单,让他们输入他们的选择,例如,为选项一输入1,等等。好吧,我不希望计数为负,所以为了处理这个问题,我让计数器类的SubtractCount方法在计数

我设计了一个简单的程序,它有一个计数器类,在这个计数器类中我有递增计数、递减计数的方法,等等。然后,我向用户展示一个菜单,让他们输入他们的选择,例如,为选项一输入1,等等。好吧,我不希望计数为负,所以为了处理这个问题,我让计数器类的SubtractCount方法在计数<0时抛出argueMetotofrangeException

然后,我让我的switch语句在异常发生时捕获该异常。我的问题是:使用异常来确保计数永远不能为负数是否不好?我应该换一种方式吗?或者更好的是,有没有更好的方法来实现这一点

代码段:

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))的计数器类创建一个方法,我的目标是确保当最终用户打开菜单时,如果选中会导致错误的菜单项将被禁用或不可用“在关口阻止他们”设计模式:)