关于在何处定位Try和Catch语句的问题

时间:2011-02-14 20:36:00

标签: c# class-design try-catch

我已经使用try和catch语句作为一种简单的方法来保持我的代码运行而不会崩溃(我会把所有内容都包装好)。最近,我想开始更正确地使用try和catch语句。这里作为一个例子我有疑问:

public class Ninja{
    Ninja(){
    }

    public void ThrowShirikin(int numberOfShirikins){
        try{
            if(numberOfShirikins == 0){
                throw new System.ArgumentException("Invalid number of shirikins");
            }

            //Throw shirikin
        }
        catch(ArgumentException e){
            MessageBox.Show(e.Message);
        }
    }
}

在上面的Ninja类中,我的ThrowShirikin方法的全部内容都包含在try循环中。由于输入错误只有一次机会(在这种情况下,当numberOfShirikins == 0时),不仅应该检查这个代码行包含在try循环中吗?见下文:

public class Ninja{
    Ninja(){
    }

    public void ThrowShirikin(int numberOfShirikins){
        bool errorsExist = false;
        try{
            if(numberOfShirikins == 0){
                errorsExist = true;
                throw new System.ArgumentException("Invalid number of shirikins");
            }
        }
        catch(ArgumentException e){
            MessageBox.Show(e.Message);
        }

        if(!errorsExist){
            //Throw shirikin
        }
    }
}

^但我在这里看起来有点笨重。关于我如何理解try catch语句的使用的任何建议和意见?谢谢!

编辑:

或者我可以这样做,所以//如果numberOfShirikins的值无效,则抛出shirikin代码永远不会执行?:

public class Ninja{
    Ninja(){
    }

    public void ThrowShirikin(int numberOfShirikins){
        try{
            if(numberOfShirikins == 0){
                throw new System.ArgumentException("Invalid number of shirikins");
                return;
            }
        }
        catch(ArgumentException e){
            MessageBox.Show(e.Message);
        }

        //Throw shirikin
    }
}

9 个答案:

答案 0 :(得分:5)

当您抛出ArgumentException之类的异常时,您不应该在方法中捕获它们。将此工作交给客户提供方法。

答案 1 :(得分:4)

看起来try/catch仅用于捕获您选择创建和抛出的异常,然后您只是为了向用户弹出消息框而捕获它。然后您选择继续或不基于错误条件。

取消trycatch。消除消息框。 执行为无效参数抛出异常。让函数的调用者确定他们是否想要捕获以及他们想要如何处理。你的Ninja课程不应该做出这些决定,除了确定什么是有效的,什么不是。

if (numberOfShirikins == 0)
    throw new ArgumentException("...");

// rest of your shirikin throwing code

答案 2 :(得分:2)

你永远不应该以这种方式捕获异常。只捕获您实际可以处理的异常。

public class Ninja{
    Ninja(){
    }

    public void ThrowShirikin(int numberOfShirikins){
            if(numberOfShirikins <= 0){
                throw new System.ArgumentException("Invalid number of shirikins");
            }
        //Throw shirikin
    }
}

我建议您在不使用try / catch的情况下开始编程。然后修复你看到的任何异常,不要隐藏它们。

答案 3 :(得分:1)

没有真正的理由在同样的方法中捕获异常。没有:

public class Ninja{
    Ninja(){
    }

    public void ThrowShirikin(int numberOfShirikins){
        if(numberOfShirikins == 0){
            MessageBox.Show(e.Message);
            return;
        }

        //...
    }
}

答案 4 :(得分:1)

一个方法不应该捕获它自己抛出的异常 - 生成它们很好,但是要明白它们很昂贵并且正常的流量控制是首选(它更容易推理等等)。

此外,在上面的示例中,errorsExist永远不会设置为true - 应该放在catch块中,而不是直接放在您抛出异常的位置。这终止了正常的程序流程。

重申,方法看起来像这样。

public void ThrowShirikin(int numberOfShirikins) {
    if(numberOfShirikins == 0){
        throw new System.ArgumentException("Invalid number of shirikins", "numberOfShirikins");
    }

    //Throw shirikin
}

这将由调用该方法的类来决定如何处理异常。

答案 5 :(得分:1)

两者都不是好主意。抛出异常并以相同的方法捕获它并从该类显示表单对话框是没有意义的。

只有应包含GUI代码的类才是GUI中的类。

在你的情况下,我也不会使用异常,我会使用布尔返回值:

public bool ThrowShirikin(int numberOfShirikins){
            if(numberOfShirikins == 0){
                return false;
            }
            //throw
            return true;
    }

例外情况应该用于例外情况,而不是一般情况。

另外,请注意,第二种方式的errorsExist = true;代码永远不会被调用,因为它低于throw语句。

答案 6 :(得分:1)

当你抛出一个异常时,你基本上会说:“这是一种特殊的情况,我不知道如何处理(或者更高的另一种方法会更好地了解应该如何处理)”< / p>

那么你刚发布的方法就是说:“当我被要求扔掉0个手里剑时,我不知道该怎么办。其实我撒了谎,我要打个招呼信息”

要么一起跳过异常并显示消息(不理想,但比抛出更好),或者只是抛出异常并在UI代码中将其捕获。如果要特别处理此特定类型,可能需要创建自己的异常类型。

答案 7 :(得分:0)

IMO - 异常在您的代码中实际上是异常条件 - 即无法预料的条件和/或错误在真正异常条件下出错的情况。

如果您上面显示的代码段,numberOfShirikins == 0不是例外情况,那么这是正常的参数检查

所以,我会将代码重新分解为:

public class Ninja{
    Ninja(){
    }

    public void ThrowShirikin(int numberOfShirikins){
        bool errorsExist = false;
        try{
            if(numberOfShirikins == 0){ showUserMessage("Invalid number of shirikins", MessageType.Information); }
        }
        catch(ArgumentException e){
            showUserMessage(e.Message, MessageType.Exception, e);
        }

        if(!errorsExist){
            //Throw shirikin
        }
    }
   private showUserMessage(string message, MessageType type, Exception ex = null){
        MessageBox.Show(message);
   }

}

完成此操作后,您会发现实际上没有为捕获异常添加任何值,因此我们可以编写一个通用异常处理程序来显示异常&amp;让你的代码正常流通。

现在,我的代码看起来像是:

public class Ninja{
        Ninja(){
        }

        public void ThrowShirikin(int numberOfShirikins){
                if(numberOfShirikins == 0){ showUserMessage("Invalid number of shirikins", MessageType.Information); return; }
                else{ /* do something here */ }
        }

另一方面,如果numberOfShirikins == 0是异常条件,那么我将编写一个自定义异常,代码为:

public class Ninja{
        Ninja(){
        }

        public void ThrowShirikin(int numberOfShirikins){
                if(numberOfShirikins == 0){ throw NumberOfShirikinsException(); }
                else{ /* do something here */ }
        }

答案 8 :(得分:0)

如果你可以避免抛出异常,你应该这样做。它们花费大约1000-4000个时钟周期。