C#如何处理完全相同的多个异常?

时间:2009-11-10 09:09:31

标签: c# asp.net .net exception

在我的代码中,我有一个带有多个catch语句的方法,它们执行所有相同的语句。我不确定这是实现这个的正确方法。你会怎么做?

public void LoadControl(ControlDestination controlDestination, string filename, object parameter)
{
    try
    {
        // Get filename with extension
        string file = GetControlFileName(filename);

        // Check file exists
        if (!File.Exists(file))
            throw new FileNotFoundException();

        // Load control from file
        Control control = LoadControl(filename);

        // Check control extends BaseForm
        if (control is BaseForm)
        {
            // Set current application on user control
            ((BaseForm)control).CurrentApplication = this;
            ((BaseForm)control).Parameter = parameter;

            // Set web user control id
            control.ID = filename;

            Panel currentPanel = null;

            switch (controlDestination)
            {
                case ControlDestination.Base:
                    // Set current panel to Base Content
                    currentPanel = pnlBaseContent;
                    // Set control in viewstate
                    this.BaseControl = filename;
                    break;
                case ControlDestination.Menu:
                    // Set current panel to Menu Content
                    currentPanel = pnlMenuContent;
                    // Set control in ViewState
                    this.MenuBaseControl = filename;
                    break;
            }

            currentPanel.Controls.Clear();
            currentPanel.Controls.Add(control);
            UpdateMenuBasePanel();
            UpdateBasePanel();

        }
        else
        {
            throw new IncorrectInheritanceException();
        }
    }
    catch (FileNotFoundException e)
    {
        HandleException(e);
    }
    catch (ArgumentNullException e)
    {
        HandleException(e);
    }
    catch (HttpException e)
    {
        HandleException(e);
    }
    catch (IncorrectInheritanceException e)
    {
        HandleException(e);
    }

}

这就是HandleException的样子:

private void HandleException(Exception exception)
{
    // Load error control which shows big red cross
    LoadControl(ControlDestination.Menu, "~/Controls/Error.ascx", null);

    // Store error in database
    DHS.Core.DhsLogDatabase.WriteError(exception.ToString());

    // Show error in errorbox on master
    Master.ShowAjaxError(this, new CommandEventArgs("ajaxError", exception.ToString()));
}

6 个答案:

答案 0 :(得分:12)

您做得对(您应该只捕获您要处理的异常,并且无法在一个catch块中捕获多个异常类型),但作为替代方案,您可以只需catch(Exception ex),检查异常类型,如果它不是你想要的那个throw那么,就像这样:

var exceptionTypes=new Type[] {
    typeof(FileNotFoundException),
    typeof(ArgumentNullException),
    //...add other types here
};

catch(Exception ex) {
    if(exceptionTypes.Contains(ex.GetType()) {
        HandleException(ex);
    } else {
        throw;
    }
}

更新:使用C#6(与Visual Studio 2015一起使用),您可以执行以下操作:

catch(Exception ex) when (exceptionTypes.Contains(ex.GetType()) {
    HandleException(ex);
}

答案 1 :(得分:3)

我重构如下: -

public class Sample
{
    public void LoadControl( ControlDestination controlDestination, string filename, object parameter )
    {
        HandleExceptions( HandleException, () =>
        {
            //.... your code
        } );
    }

    private void HandleExceptions( Action<Exception> handler, Action code )
    {
        try
        {
            code();
        }
        catch ( FileNotFoundException e )
        {
            handler( e );
        }
        catch ( ArgumentNullException e )
        {
            handler( e );
        }
        catch ( HttpException e )
        {
            handler( e );
        }
        catch ( IncorrectInheritanceException e )
        {
            handler( e );
        }
    }

    private void HandleException( Exception exception )
    {
        // ....
    }
}

如果我使用VB.NET,我会使用异常过滤器来执行一系列捕获。但是当我们使用C#时,你拥有的方法是最有效的方法而不是

private void HandleExceptions( Action<Exception> handler, Action code )
    {
        try
        {
            code();
        }
        catch ( Exception e )
        {
            if ( e is FileNotFoundException
                || e is ArgumentNullException
                || e is HttpException
                || e is IncorrectInheritanceException )
                handler( e );
            else
                throw;
        }
    }

答案 2 :(得分:3)

只要你不介意使用Lambda,你就可以使用泛型来获得更好的解决方案。我不是开启类型的粉丝。我已经使用过几次这段代码了,我觉得它对于服务代理来说尤其方便,你需要以同样的方式处理许多异常。如上所述,在可能的情况下,始终最好能够捕获正确的异常类型。

代码通过将异常指定为handle函数的泛型类型参数来工作。然后捕获这些特定类型,但作为基类传递给通用处理程序。我没有添加HandleAndThrow,但可以根据需要添加。也可以根据自己的喜好更改命名。

    public static void Handle<T>(Action action, Action<T> handler)
        where T : Exception
    {
        try
        {
            action();
        }
        catch (T exception)
        {
            handler(exception);
        }
    }

    public static void Handle<T1, T2>(Action action, Action<Exception> handler)
        where T1 : Exception
        where T2 : Exception
    {
        try
        {
            action();
        }
        catch (T1 exception)
        {
            handler(exception);
        }
        catch (T2 exception)
        {
            handler(exception);
        }
    }

    public static void Handle<T1, T2, T3>(Action action, Action<Exception> handler)
        where T1 : Exception
        where T2 : Exception
        where T3 : Exception
    {
        try
        {
            action();
        }
        catch (T1 exception)
        {
            handler(exception);
        }
        catch (T2 exception)
        {
            handler(exception);
        }
        catch (T3 exception)
        {
            handler(exception);
        }
    }

    public static void Handle<T1, T2, T3, T4>(Action action, Action<Exception> handler)
        where T1 : Exception
        where T2 : Exception
        where T3 : Exception
        where T4 : Exception
    {
        try
        {
            action();
        }
        catch (T1 exception)
        {
            handler(exception);
        }
        catch (T2 exception)
        {
            handler(exception);
        }
        catch (T3 exception)
        {
            handler(exception);
        }
        catch (T4 exception)
        {
            handler(exception);
        }
    }
}

public class Example
{
    public void LoadControl()
    {
        Exceptions.Handle<FileNotFoundException, ArgumentNullException, NullReferenceException>(() => LoadControlCore(10), GenericExceptionHandler);   
    }

    private void LoadControlCore(int myArguments)
    {
        //execute method as normal
    }

    public void GenericExceptionHandler(Exception e)
    {
        //do something
        Debug.WriteLine(e.Message);
    }        
}

答案 3 :(得分:0)

像这样写:

try
{
  // code that throws all sorts of exceptions
}
catch(Exception e)
{
  HandleException(e);
}

编辑:请注意,这是对您的问题的直接回答,而不是评论是否是推荐的做法。

edit2:您可以在函数中测试e的类型是否是特定的异常列表,如果不是,则可以重新抛出它。异常处理性能不是问题,因为它首先应该是......特殊的。

答案 4 :(得分:0)

我将以语言无关的方式回答这个问题:

1.你现在所做的是正确的。它没有任何问题,除非你多次这样做可能会变得乏味。

2.抓住最常见的例外形式。简单

catch(Exception e)
{
    ...
}

3.也许你只想抓住一些例外,而不是捕捉所有异常,如果你刚刚做了#2,那就是你要做的事情。

执行您在#2中所做的操作,并修改HandleException以仅处理某些类型的异常。这样你只需要输出一次tem,它仍然比上面更紧凑。

private void HandleException(Exception e) throws Excpetion
{
    // Reject some types of exceptions
    if (!((e is FileNotFoundException) ||
        (e is ArgumentNullException) ||
        (e is HttpException ) ||
        (e is IncorrectInheritanceException )))
    {
        throw;
    }

    //Rest of code
    ...
}

编辑:

我看到Konamiman有第三个选项improved version。我说要去那。

答案 5 :(得分:0)

我会这样做

public void LoadControl(ControlDestination controlDestination, string filename, object parameter)
{
    try
    {
        // Get filename with extension
        string file = GetControlFileName(filename);

        // Check file exists
        if (!File.Exists(file))
            throw new FileNotFoundException();

        // Load control from file
        Control control = LoadControl(filename);

        // Check control extends BaseForm
        if (control is BaseForm)
        {
            // Set current application on user control
            ((BaseForm)control).CurrentApplication = this;
            ((BaseForm)control).Parameter = parameter;

            // Set web user control id
            control.ID = filename;

            Panel currentPanel = null;

            switch (controlDestination)
            {
                case ControlDestination.Base:
                    // Set current panel to Base Content
                    currentPanel = pnlBaseContent;
                    // Set control in viewstate
                    this.BaseControl = filename;
                    break;
                case ControlDestination.Menu:
                    // Set current panel to Menu Content
                    currentPanel = pnlMenuContent;
                    // Set control in ViewState
                    this.MenuBaseControl = filename;
                    break;
            }

            currentPanel.Controls.Clear();
            currentPanel.Controls.Add(control);
            UpdateMenuBasePanel();
            UpdateBasePanel();

        }
        else
        {
            throw new IncorrectInheritanceException();
        }
    }
    catch (Exception e)
    {
        HandleException(e);
    }
}


public void HandleException(Exception e)
{
    if (e is FileNotFoundException
            || e is ArgumentNullException
            || e is HttpException
            || e is IncorrectInheritanceException)
    {
        // Load error control which shows big red cross
        LoadControl(ControlDestination.Menu, "~/Controls/Error.ascx", null);

        // Store error in database
        DHS.Core.DhsLogDatabase.WriteError(exception.ToString());

        // Show error in errorbox on master
        Master.ShowAjaxError(this, new CommandEventArgs("ajaxError", exception.ToString()));
    }
}