我这个技术博客被冷落了近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,如需转载请自行联系原作者