15

这个问题接近我想要做的,但不完全在那里。

有没有办法简化下面的代码?

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 块。我是否遗漏了什么,或者这是否公然反对代码重用?

我只是想(太)懒惰吗?

4

11 回答 11

24

您可以使用 :

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;
}
于 2009-08-20T09:55:38.703 回答
8

如果异常共享一个公共超类,那么您可以捕获该超类。

于 2009-08-20T09:53:35.803 回答
3

是的,你试图变得懒惰,但懒惰是程序员的美德之一,所以这很好。

至于您的问题:我不知道,但有一些可用的解决方法:

  • 给异常一个共同的祖先。我认为这在您的情况下是不可能的,因为它们似乎是内置的。
  • 尽可能捕捉最通用的异常。
  • 将处理代码移动到它自己的函数中,并从每个 catch 块中调用它。
于 2009-08-20T09:55:46.550 回答
2

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

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

假设你可以这样做:

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

现在是什么类型ex?他们都有,.Message因为他们继承System.Exception,但尝试访问他们的任何其他属性,你有一个问题。

于 2009-08-20T10:00:33.763 回答
2

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

于 2009-08-20T10:04:41.447 回答
2

只是为了完整起见:

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

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

Catch只有在指定的异常情况下才会输入这样的块——与 C# 不同。

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

MSDN:如何:在 Visual Basic 中的 Catch 块中筛选错误

于 2009-08-20T10:48:36.380 回答
1

查看EntLib的异常处理应用程序块。他们阐明了一种非常好的基于策略和配置的异常处理方法,可以避免大的条件逻辑块。

于 2009-08-21T07:49:20.330 回答
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;            
}
于 2009-08-20T09:52:44.980 回答
0

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

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

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

于 2009-08-20T09:54:56.240 回答
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;
于 2009-08-20T10:14:57.633 回答
0

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

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

于 2009-08-20T10:23:15.543 回答