C# Lazy

前言

合理服用 Lazy<T> 类,可以获得以下两个强大的功效:

1,延迟实例化类,提高应用程序运行效率。
2,实现高效的线程安全的单例。

一,延迟实例化类,提高程序运行效率

对于一个体格庞大、功能繁多的应用程序,启动的时候需要实例化很多对象,以便日后使用。但是有个问题,有些实例化的对象可能一次都不会被用到,那么这个对象的实例化过程就是无效的且是浪费时间的。

.NET 4.0 以后,Lazy<T> 类就可以解决这个问题,在使用到这个类的时候,才回去实例化这个类:

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            Lazy<Nlog> nlog = new Lazy<Nlog>();

            //Nlog 是否被创建
            Console.WriteLine(nlog.IsValueCreated);

            nlog.Value.Info("Lazy 测试");

            Console.WriteLine(nlog.IsValueCreated);

            Console.ReadKey();
        }
    }

    class Nlog
    {
        public void Info(string msg)
        {
            Console.WriteLine("{0} 已存入 Info",msg);
        }
        public void Error(string msg)
        {
            Console.WriteLine("{0} 已存入 Error", msg);
        }
    }
}

执行结果:

二、实现高效的线程安全的单例。

在多线程环境中,最经典的单例模式就是 “两次加锁”。而使用 Lazy<T> ,一次锁都不用加,就是这么强。如下,写一个日志类的单例:

public class Nlog
{
    private Nlog()
    {
        //保护类不被外部实例化
    }

    //单例, true 表示适用于多线程
    public static Lazy<Nlog> Instance = new Lazy<Nlog>(() => new Nlog(), true);

    public bool Info(string msg)
    {
        Console.WriteLine("{0} 已存入 Info", msg);
        return true;
    }

    public bool Error(string msg)
    {
        Console.WriteLine("{0} 已存入 Error", msg);
        return true;
    }
}
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Thread start");

        Task.Factory.StartNew(() =>
        {
            var _nlog = Nlog.Instance;

            Console.WriteLine(_nlog.IsValueCreated);
            _nlog.Value.Info("普通信息");
            Console.WriteLine(_nlog.IsValueCreated);
            Console.WriteLine("Thread1 over");
        });

        Thread.Sleep(100);
        Console.WriteLine(" ");

        Task.Factory.StartNew(() => {

            var _nlog = Nlog.Instance;

            Console.WriteLine(_nlog.IsValueCreated);
            _nlog.Value.Error("异常信息");
            Console.WriteLine(_nlog.IsValueCreated);
            Console.WriteLine("Thread2 over");
        });

        Console.ReadKey();
    }
}

执行结果:

很明显,两个线程先后使用了 Nlog 类,并且是内存中的同一个对象。

发表评论