今天有新人问说:『为什么connection要使用using直接呼叫Dispose不就好了?』,所以有了这篇文章,主要写给Java转C#或是不了解为何要使用using的工程师。
上面例子是不能直接呼叫Dispose的,之前有做过Java开发的工程师应该会习惯确保资源一定释放
会编写try,finally
,像是原本简单的逻辑建立连线,释放连线
,需要编写不少的代码,以JDBC举例:
try { ..... connection.setAutoCommit(false); ..... // 一连串SQL操作 connection.commit(); } catch(Exception) { // 发生错误,撤消所有变更 if(connection != null) { try { connection.rollback(); catch(SQLException ex) { ex.printStackTrace(); } }}finally { if(connection != null) { try { connection.close(); } catch(SQLException e) { e.printStackTrace(); } }}
但是在C#我们可以简单使用using达到同等效果,我们只需要编写
SqlConnection cn = null;using ( cn = new SqlConnection(this.Connection.ConnectionString)){// 一连串SQL操作}
为什么这么简单?
因为编译器帮我们做掉原本需要编写的代码,让我们反编译这段代码来看一下,会发现其实底层还是try,finally
,系统帮我们自动补齐代码,是不是很人性化。
SqlConnection sqlConnection;SqlConnection cn = sqlConnection = new SqlConnection(连线字串);try{// 一连串SQL操作}finally{if (sqlConnection != null){((IDisposable)sqlConnection).Dispose();}}
这时候系统先生出来说话了:『try,finally帮你做好了,我不可能知道你想要用甚么逻辑释放资源,麻烦你去实作Dispose方法,我会帮你呼叫它。』
使用using的类别需要实作IDisposable介面跟实作void Dispose()方法
,告诉系统要照什么逻辑释放。像是string类别没有实作IDisposable是无法使用using,会跳出CS1674 'string': type used in a using statement must be implicitly convertible to 'System.IDisposable'
举例:
class MyClass : IDisposable { // ... private bool disposed = false; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { // 释放资源逻辑 } disposed = true; } } ~MyClass() { Dispose(false); }}
补充:
感谢Cymon Dez补充,JDK7以后可以实作java.lang.AutoCloseable介面配合Try-with-resource statement达到相同目的。