.net中對(duì)象的生命周期有哪些?針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。
成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),堯都企業(yè)網(wǎng)站建設(shè),堯都品牌網(wǎng)站建設(shè),網(wǎng)站定制,堯都網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,堯都網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。程序在計(jì)算機(jī)上跑著,就難免會(huì)占用內(nèi)存資源來(lái)存儲(chǔ)在程序運(yùn)行過(guò)程中的數(shù)據(jù),我們按照內(nèi)存資源的存取方式將內(nèi)存劃分為堆內(nèi)存和棧內(nèi)存。
棧內(nèi)存,通常使用的場(chǎng)景是:對(duì)存取速度要求較高且數(shù)據(jù)量不大。
典型的棧內(nèi)存使用的例子就是函數(shù)棧,每一個(gè)函數(shù)被調(diào)用時(shí)都會(huì)被分配一塊內(nèi)存,這塊內(nèi)存被稱為棧內(nèi)存,以先進(jìn)后出的方式存取數(shù)據(jù),在函數(shù)執(zhí)行過(guò)程中不斷往函數(shù)棧中壓入(PUSH)數(shù)據(jù)(值類型數(shù)據(jù):int、float、對(duì)象的引用...),函數(shù)執(zhí)行完后又將函數(shù)棧中的數(shù)據(jù)逐個(gè)彈出(POP),由于是以操作棧的形式來(lái)存取,所以訪問(wèn)速度快。
堆內(nèi)存,從字面意思上理解就好像是倉(cāng)庫(kù)里面可以存一堆破爛,你若是需要存點(diǎn)什么東西就盡管往里面一扔,倉(cāng)庫(kù)里有的是空間。事實(shí)確實(shí)也是如此,堆內(nèi)存中可以存放大規(guī)格的數(shù)據(jù)(比如對(duì)象資源),這些數(shù)據(jù)是不適合存放在棧中的,因?yàn)闂?臻g的容量有限,這就是堆內(nèi)存相對(duì)于棧內(nèi)存的好處:容量大。但是它的缺點(diǎn)也是顯而易見(jiàn)的,那就是存取堆內(nèi)存的數(shù)據(jù)相較于存取棧內(nèi)存是非常慢的,試想一下,讓你在倉(cāng)庫(kù)里的一堆破爛里去找你想要的東西是什么感覺(jué)。
從內(nèi)存分配方式上看,堆內(nèi)存不同于棧內(nèi)存,函數(shù)棧是在每一個(gè)函數(shù)被執(zhí)行的時(shí)候被自動(dòng)分配并且函數(shù)執(zhí)行完成后自動(dòng)回收,而如果你想使用堆內(nèi)存,就得自己動(dòng)手豐衣足食。
所以你會(huì)看到c語(yǔ)言程序員會(huì)這樣去使用堆內(nèi)存:
int *p = (int*)malloc(sizeof(int)); //在堆內(nèi)存中申請(qǐng)一塊字節(jié)數(shù)為int字節(jié)數(shù)的堆內(nèi)存,并返回指向該內(nèi)存區(qū)域的指針 *p = 10; free(p); //釋放堆內(nèi)存資源
你還會(huì)看見(jiàn)c++程序員這樣寫:
Car* bmw = new Car(); //創(chuàng)建一個(gè)Car類對(duì)象,在堆內(nèi)存中存放對(duì)象數(shù)據(jù),并返回指向?qū)ο筚Y源的指針 delete bmw; //釋放堆內(nèi)存資源
當(dāng)然,沒(méi)有接觸過(guò)c/c++的小伙伴也不用驚慌,上面只不過(guò)是想讓你知道在c/c++語(yǔ)言中,程序員要是想使用堆內(nèi)存,那就必須顯式地編寫分配和釋放堆內(nèi)存資源的代碼。
有人問(wèn):使用完堆內(nèi)存資源后沒(méi)有手動(dòng)釋放它會(huì)有什么后果嗎?
答案是:由于堆內(nèi)存資源使用者未及時(shí)釋放內(nèi)存會(huì)導(dǎo)致內(nèi)存無(wú)法再次使用,從而造成內(nèi)存資源的泄漏(浪費(fèi))。
就在這個(gè)時(shí)候,c#程序員笑了,只見(jiàn)他的手指非常輕盈優(yōu)雅地在屏幕上敲出了下面這行代碼:
Car bmw = new Car();
一旁圍觀的c程序員和c++程序員驚呆了,他們不知道自己在敲代碼的時(shí)候有沒(méi)有像這樣輕松過(guò)。c++程序員用手撫摸著他那锃光瓦亮的額頭,突然眼睛里閃著光,喊道:“你還沒(méi)有釋放堆內(nèi)存的資源呢,你這樣是很危險(xiǎn)的,會(huì)內(nèi)存泄漏的,快,把釋放堆內(nèi)存的代碼寫上!”
c#程序員似乎并不為所動(dòng),舒舒服服地靠在椅子上,用余光瞟了c++程序員一眼,說(shuō):“不用慌,不用慌,這個(gè)對(duì)象在托管堆上放的好好的呢,不用我操心”,于是,c#程序員便娓娓道來(lái)(呼呼大睡)...
在.NET的世界,使用new關(guān)鍵字創(chuàng)建一個(gè)對(duì)象,首先對(duì)象資源被分配在托管堆中,然后new會(huì)返回一個(gè)指向堆上對(duì)象的引用,而不是真正的對(duì)象本身。如果在方法作用域中將引用變量聲明為本地變量,這個(gè)引用變量保存在棧內(nèi),以供應(yīng)用程序以后使用。
托管堆,顧名思義,就是托給別人管的堆,那么是誰(shuí)在管理著這個(gè)堆上的對(duì)象資源呢?
答案是:CLR(Common Lanauage Runtime),對(duì)象的實(shí)例化結(jié)束以后,GC(垃圾回收器)將會(huì)在對(duì)象不再需要時(shí)將其銷毀。
也就是說(shuō),通過(guò)允許垃圾收集器負(fù)責(zé)銷毀對(duì)象,內(nèi)存管理的麻煩就都交給CLR了,萬(wàn)事大吉。
看似問(wèn)題好像都已水落石出,無(wú)非就是將堆內(nèi)存資源回收交給了CLR去承擔(dān)。難道你就不想知道的更多一點(diǎn)?比如接著而來(lái)的問(wèn)題:
1、垃圾回收器如何判斷一個(gè)對(duì)象什么時(shí)候不再需要?
2、垃圾回收器又在什么時(shí)候會(huì)執(zhí)行垃圾清理的操作?
別急,帶著問(wèn)題慢慢往下看。
CIL的new指令— 垃圾回收的觸發(fā)者
c#中的new關(guān)鍵字最終會(huì)被編譯器翻譯成CIL的newobj指令,讓我們仔細(xì)查看一下CIL newobj指令的作用。
首先,需要明白托管堆不僅僅是一個(gè)可由CLR訪問(wèn)的隨機(jī)內(nèi)存塊。.NET垃圾回收器是堆的“清潔工”,出于優(yōu)化的目的它會(huì)壓縮空閑的內(nèi)存塊(當(dāng)需要時(shí))。為了輔助壓縮,托管堆會(huì)維護(hù)一個(gè)指針(通常被叫做下一個(gè)對(duì)象指針或者是新對(duì)象指針),這個(gè)指針用來(lái)標(biāo)識(shí)下一個(gè)對(duì)象在堆中分配的地址。
此外,newobj指令通知CLR來(lái)執(zhí)行下列的核心任務(wù):
(1)計(jì)算要分配的對(duì)象所需的全部?jī)?nèi)存(包括這個(gè)類型的數(shù)據(jù)成員和類型的基類所需的內(nèi)存)。
(2)檢查托管堆來(lái)確保有足夠的空間來(lái)放置所申請(qǐng)的對(duì)象。如果有足夠的空間,會(huì)調(diào)用這個(gè)類型的構(gòu)造函數(shù),構(gòu)造函數(shù)會(huì)返回一個(gè)指向內(nèi)存中這個(gè)新對(duì)象的引用,這個(gè)新對(duì)象的地址剛好就是下一個(gè)對(duì)象指針上一次所指向的位置。
(3)最后,在把引用返回給調(diào)用者之前,讓下一個(gè)對(duì)象指針指向托管堆中下一個(gè)可用的位置。
下面的圖解釋了在托管堆上分配對(duì)象的細(xì)節(jié)。
在c#中分配對(duì)象是一個(gè)很頻繁的操作,照這樣下去托管堆上的空間遲早會(huì)被揮霍完,所以,重點(diǎn)來(lái)了,如果CLR 發(fā)現(xiàn)托管堆沒(méi)有足夠空間分配請(qǐng)求的類型時(shí),它會(huì)執(zhí)行一次垃圾回收來(lái)釋放內(nèi)存。
當(dāng)執(zhí)行垃圾回收時(shí),垃圾收集器臨時(shí)掛起當(dāng)前進(jìn)程中的所有的活動(dòng)線程來(lái)保證在回收過(guò)程中應(yīng)用程序不會(huì)訪問(wèn)到堆。(一個(gè)線程是一個(gè)正在執(zhí)行的程序中的執(zhí)行路徑)。一旦垃圾回收完成,掛起的線程又可以繼續(xù)執(zhí)行了。還好,.NET 垃圾回收器是高度優(yōu)化過(guò)的,所以用戶很少能察覺(jué)到應(yīng)用程序中的短暫中斷。
通過(guò)對(duì)CIL的new指令作用的解讀,我們知道了:如果托管堆沒(méi)有足夠的空間分配一個(gè)請(qǐng)求的對(duì)象,則會(huì)執(zhí)行一次垃圾回收。
(講到這里c#程序員停了下來(lái),喝了口保溫杯里的枸杞紅棗大補(bǔ)茶?,清了清嗓子,繼續(xù)開(kāi)始解惑...)
應(yīng)用程序根的作用 — 區(qū)分不可到達(dá)的對(duì)象
現(xiàn)在讓我們來(lái)討論一下垃圾回收器怎樣確定什么時(shí)候“不再需要”一個(gè)對(duì)象。為了理解細(xì)節(jié),你需要知道應(yīng)用程序根的概念。
簡(jiǎn)單來(lái)說(shuō),一個(gè)根是一個(gè)引用,這個(gè)引用指向堆上面的一個(gè)對(duì)象的。嚴(yán)格來(lái)說(shuō),一個(gè)根可以有以下幾種情況:
(1) 指向全局對(duì)象的引用(盡管C#不支持,但CIL代碼允許分配全局對(duì)象)
(2)指向任何靜態(tài)對(duì)象
(3)指向一個(gè)應(yīng)用程序代碼中的局部對(duì)象
(4)指向傳入到一個(gè)函數(shù)中的對(duì)象參數(shù)
(5)指向等待被終結(jié)(finalized)的對(duì)象
(6)任何一個(gè)指向?qū)ο蟮腃PU寄存器
在一次垃圾回收的過(guò)程中,運(yùn)行環(huán)境會(huì)檢查托管堆上面的對(duì)象是否仍然是從應(yīng)用程序根可到達(dá)的。為了檢查可達(dá),CLR會(huì)建立一個(gè)代表堆上每個(gè)可達(dá)對(duì)象的圖。對(duì)象圖用來(lái)記錄所有可達(dá)的對(duì)象。同時(shí),注意垃圾回收器絕不會(huì)在圖上標(biāo)記一個(gè)對(duì)象兩次,因此避免了煩人的循環(huán)引用。
假設(shè)托管堆上有名字為A,B,C,D,E,F(xiàn)和G的對(duì)象集合。在一次垃圾回收過(guò)程中,會(huì)檢查這些對(duì)象(同時(shí)包括這些對(duì)象可能包含的內(nèi)部對(duì)象引用)是否是根可達(dá)的。一旦圖被建立起來(lái),不可達(dá)的對(duì)象(在此是對(duì)象C和F)被標(biāo)記為垃圾。
下圖是上述場(chǎng)景的一個(gè)可能的對(duì)象圖(你可以把箭頭讀作依賴或者需要,例如"E依賴于G,間接依賴于B,“A不依賴任何對(duì)象”等)。
(創(chuàng)建的對(duì)象圖是用來(lái)決定哪些對(duì)象是應(yīng)用程序根可達(dá)的。)
一旦一個(gè)對(duì)象已經(jīng)被標(biāo)記為終結(jié)(此例子中是C和F--在圖中沒(méi)有他倆),它在內(nèi)存中就被清理掉了。在此時(shí),堆上的剩余內(nèi)存空間被壓縮,這會(huì)導(dǎo)致CLR修改活動(dòng)的應(yīng)用程序根集合(和對(duì)應(yīng)的指針)來(lái)指向正確的內(nèi)存位置(這個(gè)操作是自動(dòng)透明的)。最后,調(diào)整下一個(gè)對(duì)象指針來(lái)指向下一個(gè)可用的內(nèi)存位置。
下圖闡明了清除和壓縮堆的過(guò)程。
到這里,通過(guò)對(duì)應(yīng)用程序根的作用的理解,我們知道了如何知道一個(gè)對(duì)象是“不再需要”的。通俗點(diǎn)來(lái)說(shuō)就是,這個(gè)對(duì)象在應(yīng)用程序中已經(jīng)無(wú)需被訪問(wèn)了,成為了一座“孤島”,自然也就不再需要它了。
(為了讓c++程序員能更加理解. net垃圾回收的奧妙,c#程序員繼續(xù)滔滔不絕…)
理解對(duì)象的代 — 垃圾回收過(guò)程的優(yōu)化
在嘗試找到不可達(dá)的對(duì)象時(shí),CLR并不是檢查托管堆上的每個(gè)對(duì)象。很明顯,這樣做會(huì)消耗大量時(shí)間,尤其在大型(例如現(xiàn)實(shí)中)程序中。
為了幫助優(yōu)化這個(gè)過(guò)程,堆上的每個(gè)對(duì)象被分配到一個(gè)特殊的"代”。代這個(gè)概念背后的想法很簡(jiǎn)單:對(duì)象在堆上存活的時(shí)間越長(zhǎng),接下來(lái)它繼續(xù)存在的可能性也就越大,即較舊的對(duì)象生存期長(zhǎng),較新的對(duì)象生存期短。例如,實(shí)現(xiàn)Main()的對(duì)象一直在內(nèi)存中,直到程序結(jié)束。相反,最近才被放到堆中的對(duì)象(例如在一個(gè)函數(shù)范圍里分配的對(duì)象)很可能很快就不可達(dá)。
在堆上的每個(gè)對(duì)象屬于以下的某一個(gè)代:
Generation 0: 標(biāo)識(shí)一個(gè)最近分配的還沒(méi)有被標(biāo)記為回收的對(duì)象
Generation 1: 標(biāo)識(shí)一個(gè)經(jīng)歷了一次垃圾回收而存活下來(lái)的對(duì)象(例如,他被標(biāo)記為回收,但由于堆空間夠用而沒(méi)有被清除掉)
Generation 2:標(biāo)識(shí)一個(gè)經(jīng)歷了不止一輪垃圾回收而存活下來(lái)的對(duì)象。
垃圾回收器首先會(huì)檢查generation 0的所有對(duì)象。如果標(biāo)記并清理這些對(duì)象(譯者注:因?yàn)樾聦?duì)象的生存期往往較短,并且期望在執(zhí)行回收時(shí),應(yīng)用程序不再使用第 0 級(jí)托管堆中的許多對(duì)象)后產(chǎn)生了足夠使用的內(nèi)存空間,任何存活下來(lái)的對(duì)象就被提升到Generation 1。為了理解一個(gè)對(duì)象的代如何影響回收的過(guò)程,可以查看下圖。下圖解釋了generation 0中一次垃圾回收后,存活的對(duì)象被提升的過(guò)程。
(generation 0 中的存活對(duì)象被提升到generation 1)
如果所有的generation 0對(duì)象都被檢查了,但是產(chǎn)生的內(nèi)存空間仍然不夠用,就檢查一遍generation 1中的所有對(duì)象的可達(dá)性并回收。存活下來(lái)的generation 1對(duì)象被提升到generation 2。如果垃圾回收器仍然需要額外的內(nèi)存,generation 2的對(duì)象就經(jīng)歷檢查并被回收。此時(shí),如果一個(gè)generation 2的對(duì)象存活下來(lái),它仍然是一個(gè)generation 2的對(duì)象。
其實(shí)通過(guò)對(duì)象的代的設(shè)計(jì)是想達(dá)到這么一個(gè)效果:新對(duì)象(比如局部變量)會(huì)被很快回收,而老一些的對(duì)象(如一個(gè)應(yīng)用程序?qū)ο螅┎粫?huì)被經(jīng)常騷擾。
說(shuō)到底,對(duì)象代的設(shè)計(jì)就是為了優(yōu)化垃圾回收的過(guò)程。
“我還有最后一個(gè)問(wèn)題”,c++程序員按耐不住心里一直的疑惑,說(shuō)到:“你說(shuō)了這么多都是再講托管資源,難道.net中就沒(méi)有非托管資源嗎?. net又是怎么對(duì)非托管資源進(jìn)行資源釋放的呢?”。
"這個(gè)問(wèn)題問(wèn)的好!",c#程序員大笑,于是接著又開(kāi)始解惑(吹B)…
構(gòu)建可終結(jié)對(duì)象 —非托管資源處理第一式
以一名c#開(kāi)發(fā)者的直覺(jué)告訴你,大多數(shù)的c#類都不需要顯式的清理邏輯。原因很簡(jiǎn)單:如果類型使用了其他托管對(duì)象,一切都最終會(huì)被垃圾回收。
問(wèn):那在什么時(shí)候需要顯式地清理呢?
答案是:在你使用非托管資源時(shí)(例如原始的操作系統(tǒng)文件句柄、原始的非托管數(shù)據(jù)連接或其他非托管資源),才可能需要設(shè)計(jì)一個(gè)在用完后清理自身垃圾的類。
比如說(shuō)下面這個(gè)類:
//數(shù)據(jù)庫(kù)上下文類 public class SqlDbContext { //...(其他被引用的對(duì)象實(shí)例) //類中包含的非托管資源(需要調(diào)用 Dispose()函數(shù)進(jìn)行資源的釋放) SqlConnection sqlConnection = new SqlConnection("..."); }
現(xiàn)在問(wèn)題來(lái)了,我們要在適當(dāng)?shù)臅r(shí)機(jī)調(diào)用數(shù)據(jù)庫(kù)連接類對(duì)象釋放資源的方法(SqlConnection類對(duì)象使用完后需要調(diào)用Dispose()方法釋放資源)。這個(gè)適當(dāng)?shù)臅r(shí)機(jī)當(dāng)然就是對(duì)象在被CLR進(jìn)行垃圾回收的過(guò)程中,所以問(wèn)題又來(lái)到了,有沒(méi)有一個(gè)方法是在這個(gè)時(shí)機(jī)被調(diào)用,而且是可以被擴(kuò)展的呢?
是的,我們可以利用. NET的基類System.Object中定義的名為Finalize()的虛方法,也叫作終結(jié)器方法,它是這樣的:
看到這當(dāng)然會(huì)很奇怪,不是說(shuō)有Finalize()方法,在哪,逗我?莫驚訝,其實(shí)這里的 ~Object() 就是Finalize(),只是一個(gè)語(yǔ)法糖罷了。
Finalize()的調(diào)用將(最終)發(fā)生在一次"自然的"垃圾回收或用程序通過(guò)GC.Collect()強(qiáng)制回收的過(guò)程中,所以這樣看來(lái),終結(jié)器方法就是讓類對(duì)象釋放內(nèi)部非托管資源的地方。nice,現(xiàn)在我們可以像這樣來(lái)編寫清理非托管資源的代碼:
//數(shù)據(jù)庫(kù)上下文類 public class SqlDbContext { //...(其他被引用的對(duì)象實(shí)例) //類中包含的非托管資源(需要調(diào)用 Dispose()函數(shù)進(jìn)行資源的釋放) SqlConnection sqlConnection = new SqlConnection("..."); ~SqlDbContext() { //這里清除非托管資源 this.sqlConnection.Dispose(); } }
這樣被構(gòu)建的對(duì)象被叫做可終結(jié)對(duì)象。
有關(guān)于終結(jié)過(guò)程的細(xì)節(jié),在《C#與.NET4高級(jí)程序設(shè)計(jì)(第5版)》書中是這樣描述的:
從以上的內(nèi)容我們得知:通過(guò)Finalize()來(lái)清除非托管資源的時(shí)機(jī)只能是在.NET對(duì)象被垃圾回收的過(guò)程中,而且終結(jié)過(guò)程是一個(gè)消耗不小的動(dòng)作。
問(wèn)題又來(lái)了:很多非托管資源都非常寶貴(如數(shù)據(jù)庫(kù)和文件句柄),所以這些資源應(yīng)該在使用完后盡快地被清除,而不能依靠垃圾回收的發(fā)生,那么這些資源應(yīng)該以怎樣的形式被顯示地釋放呢?
構(gòu)建可處置對(duì)象—非托管資源處理第二式
除了重寫 Finalize() 之外,類還可以實(shí)現(xiàn) IDisposable 接口,它定義了一個(gè)名為 Dispose() 的方法:
public interface IDisposable { void Dispose(); }
它的使用方法就是:在類的Dispose()方法中編寫非托管資源的釋放的代碼,程序員可以在這個(gè)對(duì)象不再需要的時(shí)候手動(dòng)調(diào)用對(duì)象的Dispose()方法來(lái)達(dá)到及時(shí)釋放非托管資源的目的。
于是你可以像這樣來(lái)編寫類:
//數(shù)據(jù)庫(kù)上下文類 public class SqlDbContext:IDisposable { //...(其他被引用的對(duì)象實(shí)例) //類中包含的非托管資源(需要調(diào)用 Dispose()函數(shù)進(jìn)行資源的釋放) SqlConnection sqlConnection = new SqlConnection("..."); public void Dispose() { //這里清除非托管資源 this.sqlConnection.Dispose(); } }
采用這種方式來(lái)釋放非托管資源的類被稱作為可處置對(duì)象。
在這里還要補(bǔ)充一點(diǎn),C#提供了一個(gè)語(yǔ)法糖來(lái)簡(jiǎn)化調(diào)用Dispose()操作,如下:
SqlDbContext context = new SqlDbContext(); try { //在此作用域內(nèi)使用SqlDbContext類對(duì)象context } finally { //確保使用完后調(diào)用Dispose()方法 context.Dispose(); }
上面這段代碼等同于下面這段代碼:
using (SqlDbContext context = new SqlDbContext()) { //在此作用域內(nèi)使用SqlDbContext類對(duì)象context }
c++程序員說(shuō):“你這還不是要自己手動(dòng)調(diào)用,如果我忘記調(diào)用 Dispose() 那豈不是一切都玩完!”
c#程序員冷笑一聲,“非也,非也,我來(lái)傳授你最后一招吧!”
非托管資源最強(qiáng)模式 — 雙劍合璧
人非圣賢,孰能無(wú)過(guò)。程序員也會(huì)有失手的時(shí)候,比如,忘記調(diào)用 Dispose() 方法...
這個(gè)時(shí)候就必須設(shè)計(jì)一個(gè)萬(wàn)無(wú)一失的方法,達(dá)到一個(gè)目的:就是不管有沒(méi)有手動(dòng)調(diào)用Dispose(),非托管資源最終都應(yīng)該被妥妥地釋放掉。為了解決這個(gè)問(wèn)題,我們可以如下去定義一個(gè)可處置對(duì)象類:
//數(shù)據(jù)庫(kù)上下文類 public class SqlDbContext:IDisposable { //...(其他被引用的對(duì)象實(shí)例) //類中包含的非托管資源(需要調(diào)用 Dispose()函數(shù)進(jìn)行資源的釋放) SqlConnection sqlConnection = new SqlConnection("..."); ~SqlDbContext() { //這里清除非托管資源 this.sqlConnection.Dispose(); } public void Dispose() { //這里清除非托管資源 this.sqlConnection.Dispose(); //跳過(guò)終結(jié)過(guò)程 GC.SuppressFinalize(this); }
關(guān)于.net中對(duì)象的生命周期有哪些問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
網(wǎng)站欄目:.net中對(duì)象的生命周期有哪些-創(chuàng)新互聯(lián)
URL網(wǎng)址:http://m.newbst.com/article14/cepige.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、建站公司、標(biāo)簽優(yōu)化、面包屑導(dǎo)航、用戶體驗(yàn)、品牌網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容