異常安全在Java和C#語言中的簡化

來源:互聯網
上載者:User

C簇語言中,C++首先在引入異常。在C++標準委員會投票之時,英國代表提出了反對意見,他們說異常差不多破壞了每個程式。如下的程式碼片段很好地展示了異常是如何把事情搞亂的

void f()
{
 T* p = new T;
 // 一些處理
 delete p;
}

 

如果處理過程引發異常拋出,那麼語句“delete p;”便不會被執行,這就導致了記憶體流失。為解決這個問題,有兩個提議,“智能指標”和垃圾收集。

英國人的反對意見是有道理,在C++中編寫異常安全的代碼,曾經困擾C++社群數年,97年至99年,終於總結了一些比較好的解決辦法。至今為止,仍然是十分困難的事情。

Java和C#是一門福士化的語言,異常安全這麼困難的技術,大多數程式員都會比較難以掌握,所以引入了一些簡化的方式。

在Java中,引入了垃圾收集的技術,程式員不用關心記憶體的回收問題了。但是還是存在其他的一些資源,例如資料庫連接、檔案控制代碼、互斥體(Mutex)等等。Java中,為了簡化對互斥體(Mutex)使用,引入了synchronized關鍵字(類似C#中的lock),使得線程的使用變得簡單。如下:

public synchronized void f1(List list) {
 synchronized (list) {
    //do something
 }
}

在C#中,則是更進了一步。為瞭解決異常安全問題,引入了lock、using兩個關鍵字管理資源。lock與Java中的synchronized對應。

Object obj = new Object();
lock (obj)
{
    //do something
}

上述代碼在不用lock的時候,是這樣寫的:

System.Threading.Monitor.Enter(obj);
try
{
    //do something
}
finally
{
    System.Threading.Monitor.Exit(obj);
}

而using則是一種和IDisposable配合使用的特別方式,或許是一種創新。
我們先看看IDisposable介面:

public interface IDisposable
{
      // Methods
      void Dispose();
}

我們看看資料連線SqlConnection的實現,SqlConnection實現了IDisposable介面,SqlConnection中大約是這樣實現:

if (disposing)
{
      
      
      this.Close();
}

在Dispose中調用了Close方法,釋放了資源。在File相關的對象,也是以類似的方式處理的。

使用Using:

using (IDbConnection conn = new SqlConnection())
{
    // do something
}

如果不是用Using,也需要保證異常安全。可以這樣寫,與上面的代碼等價:

IDbConnection conn = new SqlConnection();
try
{
    // do something
}
finally
{
    IDisposable disposableObj = conn as IDisposable;
    if (disposableObj != null)
    {
        disposableObj.Dispose();
    }
}

當然更直接的代碼是:

IDbConnection conn = new SqlConnection();
try
{
    //do something
}
finally
{
    conn.Close();
}

在C#中,using的用法,並沒有走到多遠,其實就是try ... finally方式和IDiposible介面的配合使用。

其實foreach的關鍵字也起到簡化編寫異常安全的程式碼的作用:

IList list = new ArrayList();
foreach (Object obj in list)
{
    //do something 
}

 其實相當於:

IList list = new ArrayList();
IEnumerator iter = list.GetEnumerator();
try
{
    while (iter.MoveNext())
    {
        Object obj = iter.Current;
        //do something 
    }
}
finally
{
    IDisposable disposableObj = iter as IDisposable;
    if (disposableObj != null)
    {
        disposableObj.Dispose();
    }
}

在foreach中,也使用了try ... finally,用於Dispose實現了IDisposable的IEnumerator對象。

Anders Hejlsberg曾說,在優秀的代碼中,會有大量的try...finally形式的代碼存在。為了減少try...finally的使用,C#引入了lock、using、foreach。

但是異常處理在C#中,缺少了異常規範(exception specification),這是令人遺憾,Anders Hejlsberg曾經發表過一些論述,很有道理,但是沒有異常規範的C#是令人遺憾的。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.