懒人懒类懒方法 - System.Lazy<T>-阿里云开发者社区

开发者社区> 数据库> 正文
登录阅读全文

懒人懒类懒方法 - System.Lazy<T>

简介:

 我这个技术博客被冷落了近1年之后,我觉得不能再这样下去,至少应该平均2周发一篇博文。坚持了两三篇博文之后,我觉得今天是应该写点什么了,却发现这段时间以来似乎没什么值得摆出来的,仔细回想了一遍,大概就只有Lazy<T>还有点意思,可以写写。


  Lazy<T>,正如其名,是为懒人设计的一个懒加载处理类。所谓懒加载,最简单的实现就是事先申明变量,但在实际使用的时候才创建对象实例。比如,通常会这么写一个懒加载的属性:


1
2
3
4
5
6
private IList<string> names;
public IList<string> {
    get {
        return names ?? (names == new List<string>());
    }
}


  懒加载比较典型的例子就是实现Singleton模式了。简单的Singleton通常会这样写:


1
2
3
4
5
6
7
8
9
public class Singleton1
{
    private static Singleton1 instance;
    public static Singleton1 Default
    {
        get return instance ?? (instance = new Singleton1()); }
    }
    private Singleton1() { }
}


  改写成Lazy<T>实现


1
2
3
4
5
6
7
8
9
public class Singleton2
{
    private static readonly Lazy<Singleton2> lazyInstance
            new Lazy<Singleton2>();
    public static Singleton2 Default
    {
        get return lazyInstance.Value; }
    }
}


  不过上面这个例子不是真正的单例,使用Lazy<T>的默认构造产生懒加载实例,需要T类型有公共的默认构造,否则在运行时会抛出 System.MissingMemberException。所以单例里其实应该用


1
Lazy<T>(Func<T>)


  所以再改写


1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton3
{
    private static readonly Lazy<Singleton3> lazyInstance
            new Lazy<Singleton3>(Create);
    public static Singleton3 Default
    {
        get return lazyInstance.Value; }
    }
    private static Singleton3 Create()
    {
        return new Singleton3();
    }
    private Singleton3() { }
}


  这么看来,Lazy<T>实现的代码貌似更多,没能偷到懒……不过,如果要求线程安全的Singleton呢,一般会这么实现:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Singleton4
{
    private static Singleton4 instance;
    private static readonly object locker = new object();
    public static Singleton4 Default
    {
        get
        {
            if (instance == null)
            {
                lock (locker)
                {
                    if (instance == null)
                    {
                        instance = new Singleton4();
                    }
                }
            }
            return instance;
        }
    }
    private Singleton4() { }
}


  这段代码,又是锁又是判断的,光“instance == null”就判断了两次,为什么?想不明白就Google,再搞不懂就看个没这么复杂的实现


1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton5
{
    private static readonly Lazy<Singleton5> lazyInstance
            new Lazy<Singleton5>(Create, true);
    public static Singleton5 Default
    {
        get return lazyInstance.Value; }
    }
    private static Singleton5 Create()
    {
        return new Singleton5();
    }
    private Singleton5() { }
}


  也就是说,从线程不安全到线程安全,只换了个Lazy<T>的构造方法,多加了一个布尔参数就解决了——简单方便。Lazy<T>提供了6个构造方法,它的文档已经写得很清楚,就不多说了。


  还要说明的一点是,懒加载当然不只是为了Singleton而设计的,就拿本文中的第一个例子来说,它有可能会有更复杂也更实际一点的实现(需要的时候再从数据库去获取数据):


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Blabla
{
    private readonly Lazy<IList<string>> lazyNames;
    public Blabla()
    {
        lazyNames = new Lazy<IList<string>>(GetNameList);
    }
    private IList<string> GetNameList()
    {
        DataTable data = dbHelper.getUsers();
        List<string> names = new List<string>();
        foreach (DataRow row in data.Rows)
        {
            names.Add(row["name"].ToString());
        }
        return names;
    }
    public IList<string> Names
    {
        get return lazyNames.Value; }
    }
}


  本文转自边城__ 51CTO博客,原文链接:http://blog.51cto.com/jamesfancy/1365402,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
数据库
使用钉钉扫一扫加入圈子
+ 订阅

分享数据库前沿,解构实战干货,推动数据库技术变革

其他文章