C#中如何合理的釋放非託管記憶體?在本文中我們將講解使用IDisposable釋放託管記憶體和非託管記憶體。
A.首先需要讓類實現IDisposable介面,然後實現IDispose方法。
A.a核心Disponse(bool isDisponse)
1.此方法首先判斷isReadyDisposed(判斷是否第一次調用此核心方法),如果不是第一次調用則不做任何操作。
2.再判斷是否是解構函式調用?如果是解構函式調用不釋放託管資源,其交由GC進行釋放,如果解構函式釋放託管資源可能之前GC釋放過,就會導致出現異常。此判斷內部釋放託管資源記憶體。
3.釋放非託管資源,並且設定標誌位isReadyDisposed=true.
B.然後分釋放託管記憶體和非託管記憶體兩種情況進行記憶體釋放處理。
B.a釋放非託管記憶體
1.釋放非託管記憶體需要手動調用本類的Dispose()方法,此方法首先調用Dispose(true)手動釋放託管和非託管資源,然後調用GC.SuppressFinalize(this),讓GC不要再調用此對象的解構函式。
B.b釋放託管記憶體
1.釋放託管記憶體是由GC自動調用解構函式,解構函式內部調用Dispose(false)方法.此時只釋放非託管資源,而託管資源不管,由GC自行釋放。
我們實現好的類代碼如下:
public class IDisponseTest : IDisposable { private bool isReadyDisposed = false; ~IDisponseTest() { //解構函式調用時不釋放託管資源,因為交由GC進行釋放 Disponse(false); } public void Dispose() { //使用者手動釋放託管資源和非託管資源 Disponse(true); //使用者已經釋放了託管和非託管資源,所以不需要再調用解構函式 GC.SuppressFinalize(this); //如果子類繼承此類時,需要按照如下寫法進行。 //try //{ // Disponse(true); //} //finally //{ // base.Disponse(); //} } public virtual void Disponse(bool isDisponse) { //isReadyDisposed是控制只有第一次調用Disponse才有效才需要釋放託管和非託管資源 if (isReadyDisposed) return; if (isDisponse) { //解構函式調用時不釋放託管資源,因為交由GC進行釋放 //如果解構函式釋放託管資源可能之前GC釋放過,就會導致出現異常 //託管資源釋放 } //非託管資源釋放 isReadyDisposed = true; } }
C#製作一個迭代器對象?使用IEnumerable、IEnumerator
首先:讓類繼承IEnumerable和IEnumerator介面,此時此類會出現IEnumerable.GetEnumerator()方法和IEnumerator.Current屬性、IEnumerator.MoveNext(),IEnumerator.Reset()方法。
其次:IEnumerator介面是對象遍曆的方法和屬性實現,而IEnumerable.GetEnumerator()方法是為了擷取IEnumerator對象。
最後:我們看看迭代器代碼實現如下執行個體:
class Program { static void Main(string[] args) { CubeEnum cubelist = new CubeEnum(50); foreach(Cube cube in cubelist) { Console.WriteLine("立方體長:" + cube.Length + ",寬" + cube.Width + ",高" + cube.Height); } Console.Read(); } } //立方體,長、寬、高 public class Cube { public int Length { get; set; } public int Width { get; set; } public int Height { get; set; } } /// <summary> /// 立方體迭代集合,繼承了IEnumerable和IEnumerator /// </summary> public class CubeEnum : IEnumerable, IEnumerator { //索引 public int Index { get; set; } //立方體集合 public Cube[] cubelist { get; set; } //初始化立方體集合 public CubeEnum(int count) { this.Index = -1; cubelist = new Cube[count]; for (int i = 0; i < count; i++) { cubelist[i] = new Cube(); cubelist[i].Length = i * 10; cubelist[i].Width = i * 10; cubelist[i].Height = i * 10; } } //實現IEnumerable的 GetEnumerator() 方法獲得IEnumerator對象 public IEnumerator GetEnumerator() { return (IEnumerator)this; } //當前Cube立方體 public object Current { get { return cubelist[Index]; } } //往下一步移動 public bool MoveNext() { Index++; if (Index < cubelist.Length) { return true; } return false; } //重設索引 public void Reset() { Index = -1; } }
本文講述的是C#基礎的應用,如有差錯,敬請斧正。