C# 异常处理审查

C# 异常处理审查,c#,exception-handling,C#,Exception Handling,我想知道我是否在代码中正确处理异常,所以希望有人能给我一些关于我下面代码的想法 public IEnumerable<Job> GetAll() { try { return this._context.Jobs; } catch (SqlException ex) { //error so dispose of context this.Dispose();

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

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

    }

您不应该在丢失堆栈跟踪时简单地重新抛出异常。我可以看到你在用它们来处理这些东西,这应该在一个


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

这种方法存在一些问题:

  • 返回
    IEnumerable
    将导致代码执行延迟。即使返回
    IEnumerable
    ,在代码中也要使用
    this.\u jobsresposition.GetAll().ToList()
  • 延迟执行导致根本不调用错误处理程序,因为代码将在客户端上下文中延迟运行(即,无论您在何处使用它)
  • 使用
    块将所有
    IDisposable
    对象包装在
因此,另一种选择是:

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 !!!!!!!
    }
}
public IEnumerable GetAllJobs(){
试一试{
使用(var jobsRepository=new jobsRepository())/!!!使用依赖项注入等
{
return jobsRepository.GetAll().ToList();/!!注意:ToList()避免延迟执行
}
}捕获(CentralRepositoryException ex){
//要转到此处的日志代码
//退回给打电话的人
投掷;
}捕获(例外情况除外){
//要转到此处的日志代码
//向调用方抛出简单异常
抛出新的CentralRepositoryException(“发生了一般异常”,ex);//!!!!!包括原始错误!!!!!!!
}
}

这不是Dispose()的正确用法。如果你注意到你最后写了:

this.Dispose(); 
this._jobsRepository.Dispose(); 
这两个都指向同一个对象。为了确保只进行一次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,那么您的异常处理将不会与您的处理混淆。

他使用throw;这将保留调用堆栈。@m.edmondson在catch子句中处理对象的原因是,如果没有异常,则处理的对象仍然可用。有什么想法吗?@m.edmondson我正在捕捉异常和centralrepositoryexception@PVitt-仅当您使用单数“throw”,但他正在创建一个
新的
对象。他至少在一个catch块中使用了该对象。啊,好的。使用块中的换行将自动处理它们。我忘记了这一点,实际上我不想在每次通话后处理它,因为这会破坏上下文。因此,为什么我只在有例外的情况下才这么做这看起来像是一个代码审查问题!
SomethingDisposable foo = new SomethingDisposable();
try
{
    //...
}
finally
{
    ((IDisposable)foo).Dispose();
}
class MyDisposable : IDisposable
{
    private SomethingDisposable foo = new SomethingDisposable();

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