异常处理审核

时间:2011-10-11 12:42:00

标签: c# exception-handling

我想知道我是否在我的代码中正确处理异常,所以希望有人会对我的代码给我一些想法

 public IEnumerable<Job> GetAll() {
        try {
            return this._context.Jobs;
        } catch (SqlException ex) {
            //error so dispose of context
            this.Dispose();
            //wrap and rethrow back to caller
            throw new CentralRepositoryException("Error getting all jobs", ex);
        }

    }

此方法是我的业务逻辑的一部分,并调用上面的方法

    public IEnumerable<Job> GetAllJobs() {
        try {
            return this._jobsRepository.GetAll();
        } catch (CentralRepositoryException ex) {
            //logging code to go here
            //throw back to caller
            throw;
        } catch (Exception ex) {
            this._jobsRepository.Dispose();
            //logging code to go here
            //throw simple exception to caller
            throw new CentralRepositoryException("A general exception has occurred");
        }
    }

我的自定义异常

public class CentralRepositoryException : System.Exception {
    public CentralRepositoryException(string message, Exception innerException)
        : base(message, innerException) {
    }

    public CentralRepositoryException(string message){
    }
}

3 个答案:

答案 0 :(得分:2)

这种方法存在一些问题:

  • 返回IEnumerable<T>将导致代码延迟执行。即使您返回IEnumerable<T>,也请在代码中使用this._jobsRepository.GetAll().ToList();
  • 延迟执行导致错误处理程序根本不被调用,因为代码将在客户端上下文中延迟运行(即无论您在何处使用它)
  • IDisposable块中的所有using个对象换行

所以另一种选择是:

public IEnumerable<Job> GetAllJobs() {
    try {
        using(var jobsRepository = new JobsRepository()) // !!! Use Dependency Injection, etc
        {
              return jobsRepository .GetAll().ToList(); // !! NOTE: ToList() avoids delayed execution

        }
    } catch (CentralRepositoryException ex) {
        //logging code to go here
        //throw back to caller
        throw;
    } catch (Exception ex) {
        //logging code to go here
        //throw simple exception to caller
        throw new CentralRepositoryException("A general exception has occurred", ex); // !!!!!! INCLUDE THE ORIGINAL ERROR !!!!!!!
    }
}

答案 1 :(得分:0)

在松散堆栈跟踪时,不应该简单地重新抛出异常。我可以看到你正在使用它们处理对象,这应该在finally block中。

除非你真正处理异常,否则你不应该使用catch,因为你希望它冒泡调用堆栈以便它可以修复 - 而不是隐藏。

答案 2 :(得分:0)

这不是Dispose()的正确用法。如果你发现你最终写了:

this.Dispose(); 
this._jobsRepository.Dispose(); 

这两个都是指同一个对象。为确保您只处理一次,该类的可重复性是声明IDisposable调用dispose。

这意味着如果您创建局部变量,则在using语句中执行此操作:

using(SomethingDisposable foo = new SomethingDisposable())
{
    //...
}

或明确处置:

SomethingDisposable foo = new SomethingDisposable();
try
{
    //...
}
finally
{
    ((IDisposable)foo).Dispose();
}

如果您创建了一个字段,那么您的课程也是一次性的:

class MyDisposable : IDisposable
{
    private SomethingDisposable foo = new SomethingDisposable();

    void IDisposable.Dispose()
    {
        foo.Dispose();
    }
}

如果您以这种方式对待IDisposables,那么您的异常处理将不会与您的处置相混淆。