C#實(shí)現(xiàn)IDisposable接口釋放非托管資源
Reference
Why using finalizers is a bad idea
當(dāng)在一個(gè)類(lèi)中使用了另外一個(gè)實(shí)現(xiàn)了IDisposable的類(lèi)作為一個(gè)成員屬性時(shí), 此時(shí)這個(gè)類(lèi)就有必要也去實(shí)現(xiàn)IDisposable接口, 以確保在合適的實(shí)際釋放非托管資源, 到底該如何正確的實(shí)現(xiàn)這個(gè)接口呢? 當(dāng)然這只是需要實(shí)現(xiàn)IDisposable接口其中一種情況
完整示例
示例的Foo類(lèi)中包含了一個(gè)Stream類(lèi)型的_stream成員, 因此需要為Foo類(lèi)實(shí)現(xiàn)IDisposable模式
public class Foo : IDisposable
{
private bool _disposed;
private readonly Stream? _stream;
public Foo()
{
_stream = File.Create("1.txt", 2048);
}
~Foo()
{
CleanupUnmanagedResources();
}
private void CleanupUnmanagedResources()
{
if (_disposed) return;
// 釋放非托管資源
_stream?.Dispose();
_disposed = true;
}
public void Dispose()
{
CleanupUnmanagedResources();
GC.SuppressFinalize(this);
}
}
為什么要實(shí)現(xiàn)Foo析構(gòu)函數(shù)
因?yàn)槿诵缘娜觞c(diǎn)(??)
哈哈, 其實(shí)因?yàn)槲覀冊(cè)谑褂?code>Foo時(shí)可能會(huì)忘記手動(dòng)調(diào)用其Dispose方法, 這個(gè)時(shí)候如果沒(méi)有析構(gòu)函數(shù)的話, 很可能導(dǎo)致資源永遠(yuǎn)得不到釋放最終釀成內(nèi)存泄漏的慘劇.
當(dāng)然啦, 在析構(gòu)函數(shù)中釋放非托管資源可能會(huì)給GC帶來(lái)額外的開(kāi)銷(xiāo), 所以最好的做法是依然是使用using塊保證能夠及時(shí)的調(diào)用Dispose方法, 這里使用析構(gòu)函數(shù)只是為了防止意外的發(fā)生. 至于為什么說(shuō)在析構(gòu)函數(shù)中釋放非托管資源會(huì)導(dǎo)致額外的GC開(kāi)銷(xiāo)呢, 這涉及到GC回收過(guò)程,GC在處理包含析構(gòu)函數(shù)的類(lèi)時(shí)不會(huì)立即將此類(lèi)回收, 而是會(huì)被GC標(biāo)記為下一代, 這樣這個(gè)被標(biāo)記為下一代的類(lèi)只有在GC決定回收下一代的垃圾對(duì)象時(shí), 才會(huì)被真正回收掉, 這樣一來(lái)就會(huì)導(dǎo)致額外的內(nèi)存和性能開(kāi)銷(xiāo)了.
Dispose方法中為什么要調(diào)用GC.SuppressFinalize
GC.SuppressFinalize方法可以告訴GC不需要在調(diào)用此類(lèi)的析構(gòu)函數(shù)(Finalizers)了;
因?yàn)樵?code>Foo類(lèi)的析構(gòu)函數(shù)中調(diào)用了Foo.CleanupUnmanagedResources方法, 當(dāng)GC回收此類(lèi)調(diào)用此類(lèi)析構(gòu)函數(shù)時(shí), 有可能會(huì)導(dǎo)致兩次調(diào)用Foo.CleanupUnmanagedResources(第一次是Dispose方法中調(diào)用的)導(dǎo)致額外的開(kāi)銷(xiāo),
所以當(dāng)我們手動(dòng)調(diào)用了Foo.Dispose(通過(guò)是通過(guò)using語(yǔ)法糖)后, 就需要告訴GC, "你回收我的時(shí)候用不著調(diào)用我的析構(gòu)函數(shù)了, 該釋放的資源我早就釋放掉了已經(jīng)", 轉(zhuǎn)換成代碼就是GC.SuppressFinalize
以上就是C#實(shí)現(xiàn)IDisposable接口釋放非托管資源的詳細(xì)內(nèi)容,更多關(guān)于C# IDisposable接口釋放資源的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#對(duì)list列表進(jìn)行隨機(jī)排序的方法
這篇文章主要介紹了C#對(duì)list列表進(jìn)行隨機(jī)排序的方法,涉及C#操作list列表的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04
相對(duì)路徑和絕對(duì)路徑的寫(xiě)法總結(jié)
本文主要對(duì)相對(duì)路徑和絕對(duì)路徑的寫(xiě)法進(jìn)行總結(jié)。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01
C#隨機(jī)數(shù)(Random)生成與應(yīng)用實(shí)戰(zhàn)之從基礎(chǔ)到高級(jí)詳解
這篇文章主要介紹了C#隨機(jī)數(shù)(Random)生成與應(yīng)用實(shí)戰(zhàn)之從基礎(chǔ)到高級(jí),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04
C#使用WebClient登錄網(wǎng)站并抓取登錄后的網(wǎng)頁(yè)信息實(shí)現(xiàn)方法
這篇文章主要介紹了C#使用WebClient登錄網(wǎng)站并抓取登錄后的網(wǎng)頁(yè)信息實(shí)現(xiàn)方法,涉及C#基于會(huì)話操作登陸網(wǎng)頁(yè)及頁(yè)面讀取相關(guān)操作技巧,需要的朋友可以參考下2017-05-05
在C#中調(diào)用VBScript、javascript等腳本的實(shí)現(xiàn)代碼
在C#中調(diào)用VBScript、javascript等腳本的實(shí)現(xiàn)步驟,需要的朋友可以參考下。2009-11-11

