精通C#--对象的生命周期

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/x13262608581/article/details/81410106

类,对象,引用

public class Car
{
    public int CurrentSpeed{get; set;}
    public string PetName{get; set;}
    public Car(){}
    public Car(string name, int speed)
    {
        PetName = name;
        CurrentSpeed = speed;
    }

    public override string ToString()
    {
        return string.Format("{0} is going {1} MPH", PetName, CurrentSpeed);
    }
}

1.应用程序根的作用
根就是一个存储位置,保存着对托管堆上一个对象的引用。
根可属于下面任何一个类别:
全局对象的引用
静态对象/静态字段的引用
应用程序代码库中局部对象的引用
传递进一个方法的对象参数的引用
等待被终结的对象的引用
任何引用对象的CPU寄存器

2.对象的代
第0代:从没有被标记为回收的新分配的对象。
第1代:在上一次垃圾回收中没有被回收的对象【被标记为回收,但因为已获取了足够的堆空间而没有被删除】。
第2代:在一次以上的垃圾回收后仍然没有被回收的对象。

3.System.GC

AddMemoryPressure(...)
RemoveMemoryPressure(...)
Collect(...)
CollectionCount(...)
GetGeneration(...)
GetTotalMemory(...)
MaxGeneration
SuppressFinalize(...)
WaitForPendingFinalizers(...)


static void Main()
{
    Console.WriteLine("***xxx***\n");
    Console.WriteLine("Estimated bytes on heap:{0}", GC.GetTotalMemory(false));
    Console.WriteLine("This OS has {0} object generations.\n", (GC.MaxGeneration + 1));
    Car refToMyCar = new Car("Zippy", 100);
    Console.WriteLine(refToMyCar.ToString());

    Console.WriteLine("\nGeneration of refToMyCar is :{0}", GC.GetGeneration(refToMyCar));

    object[] tonsOfObjects = new object[50000];
    for(int i = 0; i < 50000; i++)
        tonsOfObjects[i] = new object();

    GC.Collect(0, GCCollectionMode.Forced);
    GC.WaitForPendingFinalizers();
    Console.WriteLine("Generation of refToMyCar is:{0}", GC.GetGeneration(refToMyCar));

    if(tonsOfObjects[9000] != null)
    {
        Console.WriteLine("Generation of tonsOfObjects[9000] is {0}", GC.GetGeneration(tonsOfObjects[9000]));
    }
    else
    {
        Console.WriteLine("tonsOfObjects[9000] is no longer alive.");
    }

    Console.WriteLine();
}

4.构建可终结对象

public class Object
{
    ...
    // 将最终发生在一次自然的垃圾回收或GC.Collect()强制回收中。
    // 使用了非托管资源时,在释放对象时,释放关联的非托管资源
    protected virtual void Finalize();
    ...
}

class MyResourceWrapper
{
    ~MyResourceWrapper()
    {
        // 清除非托管资源

    }
}

C#编译器执行一个终结器语法时,自动在被隐式重写的Finalize方法中增加许多必须的基础代码。
在托管堆上分配对象时,运行库自动确定该对象是否提供一个自定义的Finalize。如提供,对象 被标记为可终结的,一个指向这个对象的指针被保存在终结队列的内部队列中。

5.构建可处置对象

public interface IDisposable
{
    void Dispose();
}

class MyResourceWrapper : IDisposable
{
    public void Dispose()
    {
        // 清除非托管资源
    }
}

class Program
{
    static void Main()
    {
        Console.WriteLine("***");
        MyResourceWrapper rw = new MyResourceWrapper();
        rw.Dispose();
        Console.ReadLine();
    }
}

static void Main()
{
    Console.WriteLine("***");
    // 退出using作用域时,自动调用Dispose
    using(MyResourceWrapper rw = new MyResourceWrapper())
    {
        // 使用rw对象
    }
}

6.构建可终结类型和可处置类型
将两种技术混合进同一个类。
如果 对象用户记住了调用Dispose,可以通过调用GC.SuppressFinalize通知垃圾回收器跳过终结过程。
如果 对象用户忘记了Dispose,对象最终也将被终结并有机会释放内部资源。

public class MyResourceWrapper : IDisposable
{
    ~MyResourceWrapper()
    {
        // 清除内部的非托管资源
        // 不调用任何托管对象的Dispose
    }

    public void Dispose()
    {
        // 在这里清除非托管资源
        // 在其它包含的可处置对象上调用Dispose

        // 如果调用了Dispose()就不需要终结,因此跳过终结
        // 通知CLR在对象被回收时不再需调用析构函数
        GC.SuppressFinalize(this);
    }
}

7.正确的处置模式

class MyResourceWrapper : IDisposable
{
    // 用来判断Dispose是否已被调用
    private bool disposed = false;
    public void Dispose()
    {
        // 调用辅助方法
        // 指定true表示对象用户触发了清理过程
        CleanUp(true);
        // 跳过终结
        GC.SuppressFinalize(this);
    }

    private void CleanUp(bool disposing)
    {
        // 保证还没被处置
        if(!this.disposed)
        {
            if(disposing)
            {
                // 释放托管的资源
            }

            // 清理非托管的资源 
        }

        disposed = true;
    }

    ~MyResourceWrapper()
    {
        // 
        CleanUp(false);
    }
}

延迟对象实例化

class Song
{
    public string Artist{get; set;}
    public string TrackName{get; set;}
    public double TraceLength{get; set;}
}

class AllTracks
{
    private Song[] allSongs = new Song[10000];
    public AllTracks()
    {
        Console.WriteLine("Filling up the songs!");
    }
}

class MediaPlayer
{
    public void Play(){...}
    public void Pause(){...}
    public void Stop(){...}
    private AllTracks allSongs = new AllTracks();
    public AllTracks GetAllTracks()
    {
        return allSongs;
    }
}

Lazy<>,该类所定义的数据在代码库实际使用它之前是不会被创建的。

class MediaPlayer
{
    ...
    private Lazy<AllTracks> allSongs = new Lazy<AllTracks>();
    // 在访问Lazy<T>::Value时,才创建T
    public AllTracks GetAllTracks()
    {
        return allSongs.Value;
    }
}

class MediaPlayer
{
    ...
    private Lazy<AllTracks> allSongs = new Lazy<AllTracks>
    (
        ()=>
        {
            Console.WriteLine("Creating AllTracks object!");
            return new AllTracks();
        }
    );

    public AllTracks GetAllTracks()
    {
        return allSongs.Value;
    }
}

猜你喜欢

转载自blog.csdn.net/x13262608581/article/details/81410106
今日推荐