在我的代码中,我有一个带有多个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()));
}
答案 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()));
}
}