是否可以在C#中扩展'using'块?

18 .net c# using-statement

有没有办法using在C#中扩展块,以便将委托作为第二个参数与IDisposable对象一起使用,并在每次在该using块内抛出异常时执行?

想象一下,我们有一个代表,如下所示:

public delegate void ExceptionHandler(Exception ex);
Run Code Online (Sandbox Code Playgroud)

假设我有一个匹配该委托的方法,如下所示:

public void Log(Exception ex)
{
  // Some logging stuff goes here
}
Run Code Online (Sandbox Code Playgroud)

我想完成这样的事情:

using(SqlConnection connection = new SqlConnection(""), Log)
{

}
Run Code Online (Sandbox Code Playgroud)

有没有办法以这种方式扩展C#?

Sef*_*efe 35

一个using块是一个速记try finally与呼叫块Disposefinally.它不能扩展为更多的东西.你想要的是a的功能try catch finally,为什么不使用它:

SqlConnection connection = new SqlConnection("");
try {

}
catch (Exception exc) {
    Log(exc);
}
finally {
    connection.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

这带来了a的所有优点try catch finally,例如捕获多个异常类型和C#6.0异常过滤器.考虑一下:

SqlConnection connection = new SqlConnection("");
try {

}
catch (SqlException exc) when (exc.Number > 0) {
    //Handle SQL error
}
catch (Exception exc) {
    Log(exc);
}
finally {
    connection.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

如果要重用标准化try catch finally块,可以使用委托:

static class ErrorHandler {
    public static ExecuteWithErrorHandling<T>(Func<T> createObject,
        Action<Exception> exceptionHandler, Action<T> operation) where T : IDisposable {

        T disposable = createObject();
        try {
            operation(disposable);
        }
        catch (Exception exc) {
            exceptionHandler(exc);
        }
        finally {
            disposable.Dispose();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以这样称呼:

ErrorHandler.ExecuteWithErrorHandling(() => new SqlConnection(""), Log, connection => {
    //Use connection here
});
Run Code Online (Sandbox Code Playgroud)

  • 既然`try catch finally`已经做到了,甚至更多,我认为我们不会看到这种情况永远存在. (11认同)

Zoh*_*led 14

您不能扩展using语句,但可以将其包装在方法中:

void DoStuff(Action action, ExceptionHandler log)
{
    using(var connction = new SqlConnection(""))
    {
        try
        {
            action();
        }
        catch(Exception e)
        {
            log(e)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)