Can you catch more than one type of exception with each block?
这个问题与我想做的很接近,但并不完全是这样。
是否有方法简化以下代码?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | private bool ValidDirectory(string directory) { if (!Directory.Exists(directory)) { if (MessageBox.Show(directory +" does not exist. Do you wish to create it?", this.Text) == DialogResult.OK) { try { Directory.CreateDirectory(directory); return true; } catch (IOException ex) { lblBpsError.Text = ex.Message; } catch (UnauthorizedAccessException ex) { lblBpsError.Text = ex.Message; } catch (PathTooLongException ex) { lblBpsError.Text = ex.Message; } catch (DirectoryNotFoundException ex) { lblBpsError.Text = ex.Message; } catch (NotSupportedException ex) { lblBpsError.Text = ex.Message; } } } return false; } |
这似乎是浪费,如果以后我想改变我向用户报告错误的方式,或者我想记录这些错误,或者其他什么,那么我必须改变5个不同的捕获块。我是缺少什么东西,还是公然反对代码重用?
我只是想变得(太)懒惰吗?
你可以使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
如果异常共享一个公共的超类,那么您只需捕获该超类。
是的,你想变得懒惰,但是懒惰是程序员的优点之一,所以这很好。
至于你的问题:我没有意识到,但也有一些解决办法:
- 给出例外的共同祖先。我认为这对你来说是不可能的,因为他们似乎是在建造。
- 捕获最一般的异常。
- 将处理代码移到它自己的函数中,并从每个catch块调用该函数。
为了完整起见:
在VB中,可以使用条件异常处理:
1 2 3 4 5 6 |
这样的
也许未来版本的C将提供类似的功能(毕竟,该代码有一个特定的IL指令)。
msdn:如何:在Visual Basic中筛选catch块中的错误
还需要注意的是,当捕获多个类型的异常时,它们应该按大多数特定的顺序排列到最一般的类型。异常将在列表中找到它匹配的第一个并抛出该错误,其他任何错误都不会被抛出。
这很烦人,其他答案都建议了很好的解决方法(我会使用@lotfi's)。
然而,考虑到C的类型安全性,这种行为是一项要求。
假设您可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 | try { Directory.CreateDirectory(directory); return true; } catch (IOException, UnauthorizedAccessException, PathTooLongException, DirectoryNotFoundException, NotSupportedException ex) { lblBpsError.Text = ex.Message; } |
现在,
从entlib中签出异常处理应用程序块。它们阐明了一种非常好的基于策略和配置的异常处理方法,避免了大型条件逻辑块。
我理解其中一些例外可能是不可预见的,但如果可能,尝试实现自己的"先发制人"逻辑。例外是昂贵的,尽管在这种情况下可能不会破坏交易。
例如,使用directory.getAccessControl(…)而不是依赖于要引发的未经授权的AccessException。
您可以使用委托,这将满足您的需要:
编辑:简化了一点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | static void Main(string[] args) { TryCatch(() => { throw new NullReferenceException(); }, new [] { typeof(AbandonedMutexException), typeof(ArgumentException), typeof(NullReferenceException) }, ex => Console.WriteLine(ex.Message)); } public static void TryCatch(Action action, Type[] exceptions, Action<Exception> catchBlock) { try { action(); } catch (Exception ex) { if(exceptions.Any(p => ex.GetType() == p)) { catchBlock(ex); } else { throw; } } } |
您的特别尝试/捕捉将是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | bool ret; TryCatch( () => { Directory.CreateDirectory(directory); ret = true; }, new[] { typeof (IOException), typeof (UnauthorizedAccessException), typeof (PathTooLongException), typeof (DirectoryNotFoundException), typeof (NotSupportedException) }, ex => lblBpsError.Text = ex.Message ); return ret; |
您可以捕获一个基类异常(您的所有异常都是从
1 2 3 4 5 6 7 8 9 | try { Directory.CreateDirectory(directory); return true; } catch (SystemException ex) { lblBpsError.Text = ex.Message; } |
但最后你可能会发现你不想捕捉的异常。
你可以做到
GETType()
请参阅http://msdn.microsoft.com/en-us/library/system.exception.gettype.aspx
编辑
1 2 3 4 5 6 7 8 9 10 11 | try { Directory.CreateDirectory(directory); return true; } catch (Exception ex) { switch(ex.GetType()) case ..... case .......... blBpsError.Text = ex.Message; } |