程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#中的IDisposable模式,

C#中的IDisposable模式,

編輯:C#入門知識

C#中的IDisposable模式,


當談到垃圾回收,在C#中,托管資源的垃圾回收是通過CLR的Garbage Collection來實現的,Garbage Collection會調用堆棧上對象的析構函數完成對象的釋放工作;而對於一些非托管資源,比如數據庫鏈接對象等,需要實現IDisposable接口進行手動的垃圾回收。那麼什麼時候使用Idisposable接口,以及如何使用呢?

 

public interface IDisposable
{
    void Dispose();
}
public class DisposablClass : IDisposable
{
    //是否回收完畢
    bool _disposed;
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    ~DisposableClass()
    {
        Dispose(false);
    }
    
    //這裡的參數表示示是否需要釋放那些實現IDisposable接口的托管對象
    protected virtual void Dispose(bool disposing)
    {
        if(_disposed) return; //如果已經被回收,就中斷執行
        if(disposing)
        {
            //TODO:釋放那些實現IDisposable接口的托管對象
        }
        //TODO:釋放非托管資源,設置對象為null
        _disposed = true;
    }
}

 

Dispose()方法

當需要回收非托管資源的DisposableClass類,就調用Dispoase()方法。而這個方法不會被CLR自動調用,需要手動調用。

 

~DisposableClass(),析構函數

當托管堆上的對象沒有被其它對象引用,GC會在回收對象之前,調用對象的析構函數。這裡的~DisposableClass()析構函數的意義在於告訴GC你可以回收我,Dispose(false)表示在GC回收的時候,就不需要手動回收了。

 

虛方法Dispose(bool disposing)

通過此方法,所有的托管和非托管資源都能被回收。參數disposing表示是否需要釋放那些實現IDisposable接口的托管對象。

 

如果disposings設置為true,就表示DisposablClass類依賴某些實現了IDisposable接口的托管對象,可以通過這裡的Dispose(bool disposing)方法調用這些托管對象的Dispose()方法進行回收。

 

如果disposings設置為false,就表示DisposableClass類依賴某些沒有實現IDisposable的非托管資源,那就把這些非托管資源對象設置為null,等待GC調用DisposableClass類的析構函數,把這些非托管資源進行回收。

 

另外,以上把Dispose(bool disposing)方法設置為protected virtual的原因是希望有子類可以一起參與到垃圾回收邏輯的設計,而且還不會影響到基類。比如有這樣的一個子類:

public class SubDisposableClass : DiposableClass
{
    private bool _disposed; //表示是否已經被回收
    protected override void Dispose(bool disposing)
    {
        if(!_disposed) //如果還沒有被回收
        {
            if(disposiing) //如果需要回收一些托管資源
            {
                //TODO:回收托管資源,調用IDisposable的Dispose()方法就可以
            }
            //TODO:回收非托管資源,把之設置為null,等待CLR調用析構函數的時候回收
            _disposed = true;
        }
        base.Dispose(disposing);//再調用父類的垃圾回收邏輯
    }
}

 

在.NET 2.0之前,如果一個對象的析構函數拋出異常,這個異常會被CLR忽略。但.NET 2.0以後,如果析構函數拋出異常就會導致應用程序的崩潰。所以,保證析構函數不拋異常變得非常重要。


還有,Dispose()方法允許拋出異常嗎?答案是否定的。如果Dispose()方法有拋出異常的可能,那就需要使用try/catch來手動捕獲。以下是考慮Dispose()方法有異常可能的寫法:

public class DisposableClass : IDisposable
{
    bool _disposed;
    ......
    protected virtual void Dispose(bool disposing)
    {
        if(_disposed) return;
        if(disposing)
        {
            //TODO:調用托管資源的Dispose()方法進行垃圾回收
        }
        try
        {
            _channelFactory.Close(); //關閉的時候可能會有異常
        }
        catch(Exception ex)
        {
            _log.Warn(ex);//記錄日志
            try
            {
                _channelFactory.Abort();//丟棄的時候可能會有異常
            }
            catch(Exception cex)
            {
                _log.Warn(cex);//記錄日志
            }
        }
        _channelFactory = null;
        _disposed = true;
    }
}

 

總結:當我們自定義的類及其業務邏輯中引用某些托管和非托管資源,就需要實現IDisposable接口,實現對這些資源對象的垃圾回收。

 

參考資料:

http://www.cnblogs.com/lori/p/3535470.html
http://lostechies.com/chrispatterson/2012/11/29/idisposable-done-right/


&在c語言中是什

&可以作為“按位與”或是“取地址”運算符
下面是作為兩種用法的介紹:
1. 按位與運算 按位與運算符"&"是雙目運算符。其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為1時,結果位才為1 ,否則為0。參與運算的數以補碼方式出現。
例如:9&5可寫算式如下: 00001001 (9的二進制補碼)&00000101 (5的二進制補碼) 00000001 (1的二進制補碼)可見9&5=1。
按位與運算通常用來對某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 運算 ( 255 的二進制數為0000000011111111)。
2.取地址
&作為一元運算符,結果是右操作對象的地址。
例如&x返回x的地址。
地址本身是一個抽象的概念,用於表示對象在存儲器中的邏輯位置
 

&在c語言中是什

&可以作為“按位與”或是“取地址”運算符
下面是作為兩種用法的介紹:
1. 按位與運算 按位與運算符"&"是雙目運算符。其功能是參與運算的兩數各對應的二進位相與。只有對應的兩個二進位均為1時,結果位才為1 ,否則為0。參與運算的數以補碼方式出現。
例如:9&5可寫算式如下: 00001001 (9的二進制補碼)&00000101 (5的二進制補碼) 00000001 (1的二進制補碼)可見9&5=1。
按位與運算通常用來對某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 運算 ( 255 的二進制數為0000000011111111)。
2.取地址
&作為一元運算符,結果是右操作對象的地址。
例如&x返回x的地址。
地址本身是一個抽象的概念,用於表示對象在存儲器中的邏輯位置
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved