你可以在每个区块中捕获多种类型的异常吗?

时间:2009-08-20 09:49:08

标签: c# try-catch

This question is close to what I want to do,但不完全在那里。

有没有办法简化以下代码?

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个不同的catch块。我是否遗漏了某些内容,或者是否公然反对代码重用?

我只是想(太)懒惰?

11 个答案:

答案 0 :(得分:23)

您可以使用:

catch (SystemException ex)
{
  if(    (ex is IOException)
      || (ex is UnauthorizedAccessException )
// These are redundant
//    || (ex is PathTooLongException )
//    || (ex is DirectoryNotFoundException )
      || (ex is NotSupportedException )
     )
       lblBpsError.Text = ex.Message;
    else
        throw;
}

答案 1 :(得分:8)

如果异常共享一个共同的超类,那么你可以捕获超类。

答案 2 :(得分:3)

是的,你试图变懒,但懒惰是the virtues of a programmer之一,所以这很好。

关于你的问题:我没有办法知道,但有一些解决方法可用:

  • 将例外视为共同的祖先。我认为在你的情况下这是不可能的,因为它们似乎是内置的。
  • 抓住最常见的例外情况。
  • 将处理代码移动到自己的函数中,并从每个catch块调用它。

答案 3 :(得分:2)

这很烦人,其他答案也提出了很好的解决方法(我会使用@ Lotfi)。

但是,考虑到C#的类型安全性,这种行为是必需的。

假设您可以这样做:

try
{
    Directory.CreateDirectory(directory);
    return true;
}
catch (IOException, 
    UnauthorizedAccessException,
    PathTooLongException,
    DirectoryNotFoundException,
    NotSupportedException ex)
{
    lblBpsError.Text = ex.Message;
}

现在什么类型ex?他们都有.Message,因为他们继承了System.Exception,但是尝试访问他们的其他任何属性,而且您遇到了问题。

答案 4 :(得分:2)

同样重要的是要注意,当捕获多种类型的异常时,它们应该按大多数顺序排列。 Exception将在列表中找到它匹配的第一个并抛出该错误,不会抛出任何其他错误。

答案 5 :(得分:2)

为了完整起见:

在VB中,您可以使用条件异常处理:

Try
    …
Catch ex As Exception When TypeOf ex Is MyException OrElse _
                           TypeOf ex Is AnotherExecption
    …
End Try

这样的Catch块只能输入指定的异常 - 与C#不同。

也许C#的未来版本将提供类似的功能(毕竟,该代码有一个特定的IL指令)。

MSDN: How to: Filter Errors in a Catch Block in Visual Basic

答案 6 :(得分:0)

你可以做到

ex.GetType()

请参阅http://msdn.microsoft.com/en-us/library/system.exception.gettype.aspx

修改

try            
{                
    Directory.CreateDirectory(directory); 
    return true;           
}            
catch (Exception ex)            
{   switch(ex.GetType())
         case .....
         case ..........
    blBpsError.Text = ex.Message;            
}

答案 7 :(得分:0)

您可以捕获基类异常(所有异常都来自SystemException):

try
{
  Directory.CreateDirectory(directory);
  return true;
}
catch (SystemException ex)
{
  lblBpsError.Text = ex.Message;
}

但是你最终可能会捕捉到你不想捕捉的异常。

答案 8 :(得分:0)

你可以使用委托,这可以做你想要的:

编辑:简化了一下

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;
         }
    }
}

您的特定尝试/捕获将是:

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;

答案 9 :(得分:0)

我理解其中一些例外可能是不可预见的,但在可能的情况下尝试实施您自己的“先发制人”逻辑。例外是昂贵的,但在这种情况下可能不是一个交易破坏者。

例如,使用Directory.GetAccessControl(...)而不是依赖于抛出UnauthorizedAccessException。

答案 10 :(得分:0)

The Exception Handling Application Block查看EntLib。他们阐述了一种非常好的基于策略和配置的异常处理方法,避免了大的条件逻辑块。