C#捕获特定异常类型的重新抛出/传播

时间:2012-01-13 15:28:10

标签: c# exception error-handling

我正在尝试将GatewayConnectionFailedException传播到我的UI,如您所见。我希望这段代码能够捕获除了我希望表示层捕获的异常之外的所有内容,以通知用户数据库是问题所以他可以去修复它。我的问题是,当我第一次抛出它时,我得到GatewayConnectionFailedException,而不是由GatewayException catch子句上的用户代码处理。

注意GatewayConnectionFailedException扩展了扩展Exception的GatewayException也很重要。有什么我缺少的东西或我是否必须将所有捕获物移动到表示层?

        try
        {
             something();
        }
        catch (GatewayConnectionFailedException gcfe)
        {
            throw;
        }
        catch (GatewayException ge)
        {
            if (ge.GetType() == typeof(GatewayConnectionFailedException))
                throw;
            string errMsg = "Records could not be retrieved due to a data gateway error. " + GetTypeInfo();
            _logger.Error(errMsg + "\r\n{0}", ge);
        }
        catch (Exception e)
        {
            if (e.GetType() == typeof(GatewayConnectionFailedException))
                throw;
            string errMsg = "Records could not be retrieved due to an unexpected error. " + GetTypeInfo();
            _logger.Error(errMsg + "\r\n{0}", e);
        }

6 个答案:

答案 0 :(得分:2)

愚蠢的问题......你的UI代码是否在尝试捕获这一层?有必要处理第二次投掷...

简而言之,听起来你正试图这样做:

using System;

namespace ConsoleApplication1
{
    class ExceptionA : Exception
    {
        public override string Message
        {
            get
            {
                return "Exception A";
            }
        }
    }

    class ExceptionB : ExceptionA
    {
        public override string Message
        {
            get
            {
                return "Exception B";
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                DoThing();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught in 'UI' code: " + ex.Message);
            }
        }

        static void DoThing()
        {
            try
            {
                throw new ExceptionB();
            }
            catch (ExceptionB ex)
            {
                Console.WriteLine("Caught B");
                throw;
            }
            catch (ExceptionA ex)
            {
                Console.WriteLine("Caught A");
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught Generic");
            }
        }
    }
}

产生此输出:

抓到B
抓住'UI'代码: 例外B
按任意键继续......

看起来你没有任何东西可以捕获第二个引发的异常,这就是为什么它“未处理”。如果我们在main中注释掉try-catch,我们最终会得到一个未处理的异常:

static void Main(string[] args)
        {
            //try
            //{
            DoThing();
            //}
            //catch (Exception ex)
            //{
            //Console.WriteLine("Caught in 'UI' code: " + ex.Message);
            //}
        }

产生以下输出:

抓到B

未处理的异常:ConsoleApplication1.ExceptionB:异常B    在C:\ Users \ Giovanni \ AppData \ Local \ T中的ConsoleApplication1.Program.DoThing() emporary Projects \ ConsoleApplication1 \ Program.cs:第50行    在C:\ Users \ Giovanni \ AppDa中的ConsoleApplication1.Program.Main(String [] args) ta \ Local \ Temporary Projects \ ConsoleApplication1 \ Program.cs:第33行 按任意键继续 。 。

答案 1 :(得分:1)

而不是throw exceptionName只使用throw

编辑1:
尝试捕获同一个块中的所有异常,然后仅在GatewayConnectionFailedException

的情况下抛出异常
try
{
     something();
}
catch (Exception e)
{
    if (e.GetType() == typeof(GatewayConnectionFailedException))
        throw;
    string errMsg = "Records could not be retrieved due to an unexpected error. " + GetTypeInfo();
    _logger.Error(errMsg + "\r\n{0}", e);
}

答案 2 :(得分:1)

虽然这可能无法解决异常问题,但是如果要捕获并重新抛出异常,请使用此代码:

catch (GatewayConnectionFailedException)
{
    throw;
}
通过这种方式,堆栈跟踪更准确地反映了程序的旅程。但它可能无法解决问题。

答案 3 :(得分:1)

如果没有完整的图片很难说出什么是遗漏,但是一个重要的事情是你应该以不同的方式抛出异常。语法应为

  

抛出;

你将拥有完整的堆栈跟踪。 More info

答案 4 :(得分:1)

抓取GatewayConnectionFailedException可以解决您的问题,在catch阻止只执行throw不要抛出异常对象。安迪的回答是正确的。

其次我假设GatewayConnectionFailedException继承自GatewayException

  

按继承顺序选择catch序列,首先应该是子类,然后是基类。

catch(Child){}
catch(Base){}
catch(Exception) {} //Base class for all exceptions

答案 5 :(得分:1)

开始尝试捕获是多余的。第一个catch将处理GatewayConnectionFailedException剩余的catch将永远不会是GatewayConnectionFailedException类型,因为它们是由第一个catch处理的。所以代码可以简化为

try
{
    something();
}
catch (GatewayConnectionFailedException)
{
    throw;
}
catch (GatewayException e)
{
    _logger.Error(e.Message, e);
}

现在UI将如何处理这取决于您如何处理异常。如果您只是抛出异常,那么您还需要在表示层中使用try catch。但是,如果此图层的返回类型返回了像

这样的对象
class Result<T>
{
     T Value {get;set;}
     Exception Error {get;set;}
}

然后你可以简单地处理类型而不需要在表示层中使用try / catch。

另外值得注意的是你正在捕捉的内容以及你为什么要抓住它。通常您不想捕获Exception,除非在您记录错误和失败的应用程序层。例外情况应该是例外情况,因此只能捕获您预期可能发生的异常以及可能发生的异常情况。否则让他们冒泡。