欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

一、前言

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

二、Dispose方法的功能

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

三、Finalize方法的機制

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

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

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

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

using System;

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

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

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

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

        }
    }
}

上面的代碼是一個近乎完美的Dispose配合Finalize的設計模板,其中有幾點需要特別注意:

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

五、總結

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

到此這篇關于C#中Dispose和Finalize方法的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • C#類的多態(tài)性詳解

    C#類的多態(tài)性詳解

    這篇文章主要為大家詳細介紹了C#類的多態(tài)性,主要有兩種:一是編譯時的多態(tài)性,二是運行時的多態(tài)性,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-10-10
  • C# 多線程學習之基礎入門

    C# 多線程學習之基礎入門

    線程(英語:thread)是操作系統(tǒng)能夠進行運算調(diào)度的最小單位。它被包含在進程之中,是進程中的實際運作單位。今天小編就帶大家了解一下C#中的多線程,快來學習一下吧
    2021-12-12
  • C# 計算傳入的時間距離今天的時間差

    C# 計算傳入的時間距離今天的時間差

    本文通過一段簡單的代碼給大家介紹了C# 計算傳入的時間距離今天的時間差,代碼簡單易懂,需要的朋友參考下吧
    2017-08-08
  • C# 擴展方法詳解

    C# 擴展方法詳解

    這篇文章主要介紹了C# 中的擴展方法的相關資料,文中講解非常細致,代碼幫助大家更好的理解和學習,感興趣的朋友可以了解下
    2021-09-09
  • C#華氏溫度和攝氏溫度相互轉(zhuǎn)換的方法

    C#華氏溫度和攝氏溫度相互轉(zhuǎn)換的方法

    這篇文章主要介紹了C#華氏溫度和攝氏溫度相互轉(zhuǎn)換的方法,涉及C#數(shù)學運算的相關技巧,非常簡單實用,需要的朋友可以參考下
    2015-07-07
  • C# 操作符之二 算數(shù)操作符

    C# 操作符之二 算數(shù)操作符

    算數(shù)操作符+,-,*,/,%,的用法和大多程序設計語言是相同的,%號的作用是整數(shù)除法中產(chǎn)生余數(shù),而整數(shù)法會直接去掉小數(shù)部分,而不是四舍五入。
    2011-02-02
  • C# WebService創(chuàng)建、發(fā)布、調(diào)用的實例講解

    C# WebService創(chuàng)建、發(fā)布、調(diào)用的實例講解

    下面小編就為大家分享一篇C# WebService創(chuàng)建、發(fā)布、調(diào)用的實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • C#使用HtmlAgilityPack抓取糗事百科內(nèi)容實例

    C#使用HtmlAgilityPack抓取糗事百科內(nèi)容實例

    這篇文章主要介紹了C#使用HtmlAgilityPack抓取糗事百科內(nèi)容的方法,實例分析了C#中HtmlAgilityPack的相關使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • C#實現(xiàn)文件上傳及文件下載功能實例代碼

    C#實現(xiàn)文件上傳及文件下載功能實例代碼

    文件上傳文件下載需求在項目中經(jīng)常會遇到,今天小編給大家分享C#實現(xiàn)文件上傳及文件下載功能實例代碼,需要的朋友參考下吧
    2017-08-08
  • WinForm判斷關閉事件來源于用戶點擊右上角“關閉”按鈕的方法

    WinForm判斷關閉事件來源于用戶點擊右上角“關閉”按鈕的方法

    這篇文章主要介紹了WinForm判斷關閉事件來源于用戶點擊右上角“關閉”按鈕的方法,涉及C#針對WinForm事件的判定技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09

最新評論