可以在另一个类,程序集或抽象类中处理异常吗?

时间:2011-10-10 22:46:44

标签: c# exception dll stack stack-trace

我发现需要多次复制并粘贴以下错误处理代码。在Catch语句中工作时我有什么选择?

  • 这样做会在此过程中丢失有价值的信息吗? (示例:异常重新包装在另一个异常中,或丢失堆栈信息)

  • 有人能说出myAbstractClass中的“throw”和下面的Select方法中的“throw”之间的区别吗?

以下是我要复制的示例代码

public class StackUserDataSource : AbstractEnhancedTableDataSource<StackUserDataServiceContext>
{
  //.. stuff

 public IEnumerable<StackUserDataModel> Select() 
    {
        try
        {
            var results = from c in _ServiceContext.StackUserTable
                          select c;

            var query = results.AsTableServiceQuery();
            var queryResults = query.Execute();

            return queryResults;
        }
        catch (StorageClientException e)
        {

           // Todo: consider sticking this in another central location    
            switch (e.ErrorCode)
            {
                case StorageErrorCode.AccessDenied:
                    break;
                case StorageErrorCode.AccountNotFound:
                    break;
                case StorageErrorCode.AuthenticationFailure:
                    break;
                // ... Yadda yadda, handle some exceptions, not others.. this is a demo.
                case StorageErrorCode.TransportError:
                    break;
                default:
                    break;
            }
            throw;
        }
    }

更新

我怀疑这是可能的,但我可以动态捕获和过滤外部库中的异常吗?概念就像这样

        try
        {
            var results = from c in _ServiceContext.StackUserTable
                          select c;

            var query = results.AsTableServiceQuery();
            var queryResults = query.Execute();

            return queryResults;
        }
        catch (MyExternalExceptionHelperDLL e)
        {
            // all exceptions referenced in MyExternalHelper are passed below
            MyExternalExceptionHelper.ProcessException(e);
         }
         catch (exception)
        {
         }

因为MyExternalExceptionHelperDLL可能无法动态选择要监听的内容(即SQL,网络与文件,但不是身份验证)

        try
        {
            var results = from c in _ServiceContext.StackUserTable
                          select c;

            var query = results.AsTableServiceQuery();
            var queryResults = query.Execute();

            return queryResults;
        }
         catch (exception e)
        {
           MyExternalExceptionHelper.ProcessException(e);

           // The problem is that I don't know how to catch exceptions thrown from that static method above,
           // or how to override that exception handling...
        }

但是使用上面的代码,我不清楚最终用户如何选择或覆盖我的事件处理方法。

2 个答案:

答案 0 :(得分:1)

您只能在throw;子句中直接调用catch,而throw e;可以在您拥有异常实例e的任何位置调用throw;。它们之间的区别在于throw e;重新抛出异常,同时保持其原始堆栈跟踪不变,而throw e;重置堆栈跟踪,以便看起来异常最初由switch抛出 - 调试时可能会很烦人。因此,我建议您将StorageClientException语句提取到以throw;作为参数的单独方法,但将catch直接保留在{{1}}子句中。

答案 1 :(得分:1)

你可以这样做。重要的是,throw需要位于原始catch块中,以便保留堆栈跟踪。

public IEnumerable<StackUserDataModel> Select() 
{
    try
    {
        ...
    }
    catch (StorageClientException e)
    {
       // You could do this if there is no fancy processing to do
       if (!IsCatchableException(e))
          throw;
    }
}

bool IsCatchableException(StorageClientException e)
{
    ... optionally do some fancy processing of the exception, e.g. logging....
    switch (e.ErrorCode)
    {
        case StorageErrorCode.AccessDenied:
        case StorageErrorCode.AccountNotFound:
        ....
        return true;
    }
}