最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#中Dispose和Finalize方法使用介紹

 更新時(shí)間:2022年03月22日 10:05:37   作者:.NET開(kāi)發(fā)菜鳥(niǎo)  
這篇文章介紹了C#中Dispose和Finalize方法的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一、前言

在C#中,由于有了垃圾回收機(jī)制的支持,對(duì)象的析構(gòu)和以前的C++有了很大的不同,這就要求程序員在設(shè)計(jì)類型的時(shí)候,充分理解.NET的機(jī)制,明確怎樣利用Dispose方法和Finalize方法來(lái)保證一個(gè)對(duì)象正確而高效地被析構(gòu)。

二、Dispose方法的功能

我們?cè)谥v解有關(guān)using的用法時(shí),已經(jīng)介紹了Dispose方法。正是因?yàn)槔厥諜C(jī)制掩蓋了對(duì)象內(nèi)存真正被回收的時(shí)間,考慮到很多情況下程序員扔希望在對(duì)象不再被使用的時(shí)候進(jìn)行一些清理工作,所以.NET提供了IDisposable接口并且在其中定義了Dispose方法。通常程序員會(huì)在Dispose方法中實(shí)現(xiàn)一些托管對(duì)象和非托管對(duì)象的釋放以及邏輯業(yè)務(wù)的結(jié)束工作等。注意實(shí)現(xiàn)了Dispose方法不能得到任何有關(guān)釋放的保證,Dispose方法的調(diào)用依賴于類型的使用者,當(dāng)類型被不恰當(dāng)?shù)厥褂脮r(shí),Dispose方法將不會(huì)被調(diào)用,但using等語(yǔ)法的存在還是幫助了類型的Dispose方法被調(diào)用。

三、Finalize方法的機(jī)制

由于Dispose方法的調(diào)用依賴于使用者,為了彌補(bǔ)這一缺陷,.NET同時(shí)提供了Finalize方法。Finalize方法常常被具有C++開(kāi)發(fā)經(jīng)驗(yàn)的程序員稱為析構(gòu)方法,但它的執(zhí)行方法卻和傳統(tǒng)C++中的析構(gòu)函數(shù)完全不同。Finalize方法在GC執(zhí)行垃圾回收時(shí)調(diào)用,具體的機(jī)制是這樣的:

  • 當(dāng)每個(gè)包含F(xiàn)inalize方法的類型的實(shí)例對(duì)象被分配時(shí),.NET會(huì)在一張?zhí)囟ǖ谋斫Y(jié)構(gòu)中添加一個(gè)引用并且執(zhí)行這個(gè)實(shí)例對(duì)象。方便起見(jiàn)稱該表為“帶析構(gòu)對(duì)象表”。
  • 當(dāng)GC執(zhí)行并且檢測(cè)到一個(gè)不被使用的對(duì)象時(shí),需要進(jìn)一步檢查“帶析構(gòu)對(duì)象表”來(lái)查看該對(duì)象類型是否有Finalize方法,如果沒(méi)有則該對(duì)象被視為垃圾,如果存在Finalize方法,則把指向該對(duì)象的引用從“帶析構(gòu)對(duì)象表”移到另外一張表中,這里暫時(shí)稱它為“等待析構(gòu)表”。并且該對(duì)象實(shí)例被視為扔在被使用。
  • CLR將有一個(gè)單獨(dú)的線程負(fù)責(zé)處理“等待析構(gòu)表”,其方法就是依次通過(guò)引用調(diào)用其中每個(gè)對(duì)象的Finalize方法,然后刪除引用,這時(shí)托管堆中的對(duì)象實(shí)例將處于不再被使用的狀態(tài)。
  • 下一個(gè)GC執(zhí)行時(shí),將釋放已經(jīng)被調(diào)用Finalize方法的那些對(duì)象實(shí)例。

四、正確地使用Dispose和Finalize方法

Finalize方法確實(shí)比Dispose方法更加安全,因?yàn)樗蒀LR保證調(diào)用,但是性能方面Finalize方法卻要差的多。我們需要知道的是:正確的類型設(shè)計(jì)是把Finalize方法作為Dispose方法的后備,只有在使用者沒(méi)有調(diào)用Dispose方法的情況下,F(xiàn)inalize方法才能被視為需要執(zhí)行。下面是一個(gè)正確高效的設(shè)計(jì)模板,建議牢記這個(gè)模板并且套用到每一個(gè)需要DIspose和Finalize方法的類型上去。

using System;

namespace usingDemo
{
    public class FinalizeDisposeBase : IDisposable
    {
        // 標(biāo)記對(duì)象是否已被釋放
        private bool _disposed = false;
        // Finalize方法
        ~FinalizeDisposeBase()
        {
            Dispose(false);
        }

        /// <summary>
        /// 這里實(shí)現(xiàn)了IDisposable中的Dispose方法
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            // 告訴GC此對(duì)象的Finalize方法不再需要調(diào)用
            GC.SuppressFinalize(true);
        }

        /// <summary>
        /// 在這里做實(shí)際的析構(gòu)工作
        /// 聲明為虛方法以供子類在必要時(shí)重寫(xiě)
        /// </summary>
        /// <param name="isDisposing"></param>
        protected virtual void Dispose(bool isDisposing)
        {
            // 當(dāng)對(duì)象已經(jīng)被析構(gòu)時(shí),不在執(zhí)行
            if(_disposed)
            {
                return;
            }
            if(isDisposing)
            {
                // 在這里釋放托管資源
                // 只在用戶調(diào)用Dispose方法時(shí)執(zhí)行
            }
            // 在這里釋放非托管資源
            // 標(biāo)記對(duì)象已被釋放
            _disposed = true;
        }
    }

    public sealed class FinalizeDispose:FinalizeDisposeBase
    {
        private bool _mydisposed = false;
        protected override void Dispose(bool isDisposing)
        {
            // 保證只釋放一次
            if (_mydisposed)
            {
                return;
            }
            if(isDisposing)
            {
                // 在這里釋放托管的并且在這個(gè)類型中聲明的資源
            }
            // 在這里釋放非托管的并且在這個(gè)類型中聲明的資源
            // 調(diào)用父類的Dispose方法來(lái)釋放父類中的資源
            base.Dispose(isDisposing);
            // 設(shè)置子類的標(biāo)記
            _mydisposed = true;
        }
        static void Main()
        {

        }
    }
}

上面的代碼是一個(gè)近乎完美的Dispose配合Finalize的設(shè)計(jì)模板,其中有幾點(diǎn)需要特別注意:

  • 真正做釋放工作的只是Virtual的受保護(hù)方法Dispose方法,事實(shí)上這個(gè)方法的名字并不重要,僅僅為了通用和更好理解,稱呼它為Dispose。
  • 虛方法Dispose需要接受一個(gè)布爾類型的參數(shù),主要用于區(qū)分調(diào)用方是類型的使用者還是.NET的垃圾回收。前者通過(guò)IDisposable的Dispose方法,而后者通過(guò)Finalize方法。兩者的區(qū)別是通過(guò)Finalize方法釋放資源時(shí)不能再釋放或使用對(duì)象中的托管資源,這是因?yàn)檫@時(shí)的對(duì)象已經(jīng)處于不被使用的狀態(tài),很有可能其中的托管資源已經(jīng)被釋放掉了。
  • 在IDisposable的Dispose方法的實(shí)現(xiàn)中通過(guò)GC.SuppressFinalize()方法來(lái)告訴.NET此對(duì)象在被回收時(shí)不需要調(diào)用Finalize方法,這一句是改善性能的關(guān)鍵,記住實(shí)現(xiàn)Dispose方法的本質(zhì)目的就是避免所有釋放工作在Finalize方法中進(jìn)行。
  • 子類型必須定義自己的釋放標(biāo)記來(lái)標(biāo)明子類中的資源是否已經(jīng)被釋放,同時(shí)子類的虛方法Dispose方法也只需要釋放自己新定義的資源。
  • 確保在虛方法Dispose中做的都是釋放工作,有些邏輯上的結(jié)束工作需要反復(fù)斟酌,以防止一個(gè)簡(jiǎn)單的賦值語(yǔ)句使對(duì)象再度存活。

五、總結(jié)

Dispose方法被使用者主動(dòng)調(diào)用,而Finalize方法在對(duì)象被垃圾回收的第一輪回收后,由一個(gè)專用的.NET線程進(jìn)行調(diào)用。Dispose方法不能保證被執(zhí)行,而.NET的垃圾回收機(jī)制保證了擁有Finalize方法并且需要被調(diào)用的類型對(duì)象的Finalize方法被執(zhí)行。調(diào)用Finalize方法涉及了一系列復(fù)雜的操作,性能代價(jià)非常高,程序員可以通過(guò)GC.SuppressFinalize方法通知.NET該對(duì)象的Finalize方法不需要被調(diào)用。有關(guān)Dispose和Finalize的類型設(shè)計(jì)應(yīng)該參照上面的代碼模板,以保證對(duì)象能夠被高效和安全的釋放。

到此這篇關(guān)于C#中Dispose和Finalize方法的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用C#實(shí)現(xiàn)讀取PDF中所有文本內(nèi)容

    使用C#實(shí)現(xiàn)讀取PDF中所有文本內(nèi)容

    這篇文章主要為大家詳細(xì)介紹了如何使用C#實(shí)現(xiàn)讀取PDF中所有文本內(nèi)容,文中的示例代碼簡(jiǎn)潔易懂,具有一定的學(xué)習(xí)價(jià)值,有需要的小伙伴可以了解下
    2024-02-02
  • C#和Java互相調(diào)用的方法小結(jié)

    C#和Java互相調(diào)用的方法小結(jié)

    這篇文章主要介紹了C#和Java互相調(diào)用的方法,文中展示了如何在不同編程語(yǔ)言之間實(shí)現(xiàn)互操作,每種語(yǔ)言之間的互操作都有其特定的方法和工具,希望這些示例能夠幫助你更好地理解和實(shí)現(xiàn)跨語(yǔ)言調(diào)用,需要的朋友可以參考下
    2025-04-04
  • c# 操作word寫(xiě)入特殊字符的實(shí)例

    c# 操作word寫(xiě)入特殊字符的實(shí)例

    這篇文章主要介紹了c# 操作word寫(xiě)入特殊字符的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • C#小數(shù)點(diǎn)格式化用法小結(jié)

    C#小數(shù)點(diǎn)格式化用法小結(jié)

    這篇文章主要介紹了C#小數(shù)點(diǎn)格式化用法,結(jié)合實(shí)例形式分析了C#小數(shù)點(diǎn)格式化運(yùn)算的常用函數(shù)與相關(guān)使用技巧,需要的朋友可以參考下
    2016-08-08
  • C#實(shí)現(xiàn)在Form里面內(nèi)嵌dos窗體的方法

    C#實(shí)現(xiàn)在Form里面內(nèi)嵌dos窗體的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)在Form里面內(nèi)嵌dos窗體的方法,涉及C#針對(duì)Form窗體的設(shè)置及使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-09-09
  • unity實(shí)現(xiàn)貼圖矩陣運(yùn)算(旋轉(zhuǎn)平移縮放)

    unity實(shí)現(xiàn)貼圖矩陣運(yùn)算(旋轉(zhuǎn)平移縮放)

    這篇文章主要為大家詳細(xì)介紹了unity實(shí)現(xiàn)貼圖矩陣運(yùn)算,旋轉(zhuǎn)平移縮放,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • C#畫(huà)筆Pen繪制光滑模式曲線的方法

    C#畫(huà)筆Pen繪制光滑模式曲線的方法

    這篇文章主要介紹了C#畫(huà)筆Pen繪制光滑模式曲線的方法,涉及C#圖形繪制畫(huà)筆Pen相關(guān)屬性的設(shè)置技巧,需要的朋友可以參考下
    2015-06-06
  • 詳解C#中三個(gè)關(guān)鍵字params,Ref,out

    詳解C#中三個(gè)關(guān)鍵字params,Ref,out

    本文主要討論params關(guān)鍵字,ref關(guān)鍵字,out關(guān)鍵字。非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2017-05-05
  • 用Linq從一個(gè)集合選取幾列得到一個(gè)新的集合(可改列名)

    用Linq從一個(gè)集合選取幾列得到一個(gè)新的集合(可改列名)

    這篇文章主要介紹了用Linq從一個(gè)集合選取幾列得到一個(gè)新的集合(可改列名),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • C#如何給PDF文件添加水印

    C#如何給PDF文件添加水印

    這篇文章主要為大家詳細(xì)介紹了C#如何給PDF文件添加水印的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09

最新評(píng)論

湘潭县| 岫岩| 游戏| 得荣县| 奉贤区| 安丘市| 加查县| 禄劝| 闽侯县| 青海省| 宁阳县| 海阳市| 兴仁县| 南宁市| 天门市| 绍兴市| 桓台县| 梅州市| 平阴县| 淮安市| 湖州市| 井冈山市| 凤冈县| 英山县| 黄山市| 婺源县| 额济纳旗| 天峻县| 西吉县| 沭阳县| 东丽区| 永福县| 阿拉善左旗| 石渠县| 林西县| 神农架林区| 新乐市| 邵阳市| 哈巴河县| 察雅县| 阿克陶县|