2011-02-08 27 views
11

我在C++/CLI程序集中有一個託管對象。作爲C++/CLI,它通過其「析構函數」實現了Disposable模式(是的,我知道它與標準的C++析構函數不同)。從C++/CLI中,我只需要delete這個對象。但是,我將此對象用作C#類中的成員變量。如何確定性地處理來自C#的託管C++/CLI對象?

從我的C#類中,我想在完成使用它時調用C++/CLI對象上的Dispose()方法的等價物。由於它是(並且必須是)該類的成員變量,因此使用using()塊是不可能的。據我所知,從C++/CLI以外的語言直接確定性地處理資源沒有任何公開的方法。我怎樣才能做到這一點?

+0

我不明白,[Dispose`]有什麼問題(http://msdn.microsoft.com/en-us/ library/system.idisposable.dispose.aspx)方法?沒有它就無法實現一次性模式。 – 2011-02-08 15:51:58

+1

C++/CLI類不公開`Dispose()`方法。它隱含在C++/CLI(如`〜MyClass`)的析構函數的語法中,但是當從C#引用對象時,您沒有暴露的Dispose()方法,就像我所知道的那樣。 – JimEvans 2011-02-08 15:54:19

回答

9

類似於C++/CLI析構函數的語法自動實現IDisposable,但它的操作方式類似於C#的explicit interface implementation。這意味着你必須轉換爲IDisposable訪問Dispose方法:

((IDisposable)obj).Dispose(); 
-2

你不能。至少,不是來自C#。讓垃圾收集器做好工作。

+0

當然可以。 C#甚至有一個關鍵字。 – 2011-02-08 16:01:49

9

這是不是在C++/CLI那麼明顯,但它的工作原理究竟它在C#的方式。您可以在使用對象瀏覽器查看課程時看到它。或者像ildasm.exe這樣的反編譯器,看看它有什麼作用。

當你編寫析構函數時,C++/CLI編譯器會自動生成一堆代碼。它實現了一次性模式,即使你沒有這樣聲明,你的類也會自動實現IDisposable。你得到一個公共的Dispose()方法,一個受保護的Dispose(bool)方法和一個自動調用GC :: SuppressFinalize()。

在C++/CLI中使用delete來顯式調用它,編譯器會發出Dispose()調用。通過使用堆棧語義,您可以在C++/CLI中獲得相當於RAII的結果,編譯器會自動在範圍塊末尾發出Dispose調用。 C++程序員熟悉的語法和行爲。

如果這個類是用C#編寫的,那麼你會在C#中做同樣的事情。您可以調用Dispose()來顯式調用,您可以使用using語句以隱式方式以異常安全的方式調用它。

否則相同的規則適用,您只需要需要析構函數,當您需要釋放一些不受管理的內存時。幾乎總是一個本地對象,即您在構造函數中分配的對象。考慮一下,如果這個非託管對象很小並且GC :: AddMemoryPressure()是一個非常體面的選擇,它可能不值得費神。但是,您必須在這樣的包裝類中實現終結器(!ClassName())。你不能強制外部客戶端代碼調用Dispose(),這樣做是可選的,並且經常被遺忘。你不希望這樣的疏忽導致非託管內存泄漏,終結器確保它仍然被釋放。通常編寫析構函數的最簡單的方法是明確調用終結器(this->!ClassName();

相關問題