99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

C# 自動(dòng)內(nèi)存管理

2018-09-28 18:42 更新

自動(dòng)內(nèi)存管理

C# 使用(employs)自動(dòng)內(nèi)存管理(automatic memory management),這解放了開發(fā)人員必須手動(dòng)分配與釋放對(duì)象內(nèi)存戰(zhàn)勇的麻煩。自動(dòng)內(nèi)存管理策略由垃圾回收器(garbage collector)實(shí)現(xiàn)。對(duì)象的內(nèi)存管理生命周期如下:

  1. 當(dāng)對(duì)象被創(chuàng)建時(shí),為它分配內(nèi)存,運(yùn)行構(gòu)造函數(shù),視該對(duì)象為存活(live)對(duì)象。
  2. 如果一個(gè)對(duì)象(或其任何一個(gè)部分)不能在后續(xù)執(zhí)行(continuation of execution)中被訪問——除了析構(gòu)函數(shù)——那么這個(gè)對(duì)象將被視為不再使用并符合銷毀條件(eligible for destruction)。C# 編譯器和垃圾回收器會(huì)選擇分析代碼,并確定哪個(gè)對(duì)象的引用在未來會(huì)被使用。比方說,如果某范圍內(nèi)某個(gè)局部變量是某對(duì)象的唯一存在的引用,但在當(dāng)前執(zhí)行點(diǎn)(current execution point)之后的所有過程中(procedure)都不會(huì)再引用這個(gè)變量,那么垃圾回收器可能(但不是絕對(duì))會(huì)理解為這個(gè)對(duì)象不再被使用。
  3. 一旦對(duì)象符合銷毀條件(eligible for destruction),那么在稍后某個(gè)時(shí)間(at some unspecified later time)將運(yùn)行這個(gè)對(duì)象的析構(gòu)函數(shù)(第十章第十三節(jié))(如果有析構(gòu)函數(shù)的話)。在正常情況下,對(duì)象的析構(gòu)函數(shù)只會(huì)運(yùn)行一次(once only),但特定實(shí)現(xiàn)(implementation-specific)的 APIs 可能會(huì)允許忽視(overridden)這個(gè)行為。
  4. 一旦運(yùn)行該對(duì)象的析構(gòu)函數(shù),那么這個(gè)對(duì)象(或其任何一部分)都不能在后續(xù)執(zhí)行中被訪問到——包括運(yùn)行中的析構(gòu)函數(shù)——這個(gè)對(duì)象將被視為不可訪問(inaccessible)并符合回收條件(eligible for collection)。
  5. 最后,在該對(duì)象符合回收條件后的某個(gè)時(shí)刻,垃圾回收器釋放分配給該對(duì)象的內(nèi)存。

垃圾回收器維護(hù)著對(duì)象使用(object usage)的信息,透過這些信息為內(nèi)存管理作出決策,諸如何處內(nèi)存存放了新建對(duì)象,何時(shí)遷移(relocate)一個(gè)對(duì)象以及一個(gè)對(duì)象何時(shí)開始不被使用或不可訪問。

和其它有垃圾回收器的語言類似,C# 的設(shè)計(jì)也在努力使垃圾回收器能實(shí)現(xiàn)更廣泛的(wide range)內(nèi)存管理策略(memory management policies)比方說,C# 并不強(qiáng)求析構(gòu)函數(shù)一定要運(yùn)行,并不強(qiáng)求對(duì)象一滿足條件就要立即被回收,并不強(qiáng)求析構(gòu)函數(shù)一定要按照某個(gè)特定順序執(zhí)行或是在某個(gè)特定線程上執(zhí)行。

垃圾回收器的行為是可控的,在某種程度上講,可以通過 System.GC 上的靜態(tài)方法(來實(shí)現(xiàn))。通過這個(gè)類可以請(qǐng)求執(zhí)行一次回收操作、運(yùn)行(或不運(yùn)行)析構(gòu)函數(shù),等。

由于垃圾回收器在決定「何時(shí)回收(collect)對(duì)象并執(zhí)行析構(gòu)函數(shù)」這一點(diǎn)上充分自由(allowed wide latitude),因此一個(gè)合格的實(shí)現(xiàn)也許會(huì)產(chǎn)生與下面所示代碼有所不同的輸出。在程序

using System;
class A
{
    ~A() {
        Console.WriteLine("Destruct instance of A");
    }
}
class B
{
    object Ref;
    public B(object o) {
        Ref = o;
    }
    ~B() {
        Console.WriteLine("Destruct instance of B");
    }
}
class Test
{
    static void Main() {
        B b = new B(new A());
        b = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

中,創(chuàng)建了 A 和 B 的實(shí)例。當(dāng) null 值被賦予變量 b 之后,這些資源成為符合回收條件,這是由于自此之后用戶所寫的任何代碼都不可能訪問到它們。輸出的結(jié)果可能是

Destruct instance of A
Destruct instance of B

或者

Destruct instance of B
Destruct instance of A

,這是由于語言并未對(duì)對(duì)象被垃圾回收的順序強(qiáng)加限制。

盡管很相近,但區(qū)別「符合銷毀條件(eligible for destruction)」與「符合回收條件(eligible for collection)」還是比較重要的,比方說:

using System;
class A
{
    ~A() {
        Console.WriteLine("Destruct instance of A");
    }
    public void F() {
        Console.WriteLine("A.F");
        Test.RefA = this;
    }
}
class B
{
    public A Ref;
    ~B() {
        Console.WriteLine("Destruct instance of B");
        Ref.F();
    }
}
class Test
{
    public static A RefA;
    public static B RefB;
    static void Main() {
        RefB = new B();
        RefA = new A();
        RefB.Ref = RefA;
        RefB = null;
        RefA = null;
        // A and B now eligible for destruction
        GC.Collect();
        GC.WaitForPendingFinalizers();
        // B now eligible for collection, but A is not
        if (RefA != null)
            Console.WriteLine("RefA is not null");
    }
}

在上面程序中,如果立即回收器(garbage collector)選擇在運(yùn)行 B 的析構(gòu)函數(shù)前先運(yùn)行 A 的析構(gòu)函數(shù),那么這個(gè)程序也許會(huì)輸出:

Destruct instance of A
Destruct instance of B
A.F
RefA is not null

注意,盡管 A 的實(shí)例未被使用,依舊調(diào)用了 A 的析構(gòu)函數(shù),同時(shí) A 的方法也有可能被其它析構(gòu)函數(shù)調(diào)用(此例中為 F)。同時(shí)還要注意,析構(gòu)函數(shù)的運(yùn)行可能導(dǎo)致對(duì)象在主程序中再次變的可訪問。在此例中,B 析構(gòu)函數(shù)的運(yùn)行導(dǎo)致了先前并未使用的 A 實(shí)例在通過引用 Test.RefA 時(shí)變得再次可訪問。在調(diào)用 WaitForPendingFinalizers 之后,B 的實(shí)例便符合回收條件了,但由于引用了 Test.RefA,所以實(shí)例 A 還不能被回收。

為了避免混淆和意外行為,建議類的析構(gòu)函數(shù)僅對(duì)自己內(nèi)部的字段數(shù)據(jù)進(jìn)行清理,不要去干涉其它所引用的對(duì)象或靜態(tài)字段。

另一個(gè)替代析構(gòu)函數(shù)的方法是讓類實(shí)現(xiàn) System.IDisposable 接口。這將允許對(duì)象的客戶端(client of the object)決定何時(shí)釋放自身資源,通常會(huì)在 using 語句(第八章第十三節(jié))通過資源的方式訪問該對(duì)象。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)