我有这段代码:
public class EntityMapper<T> where T : IMappingStrategy, new()
{
private static T currentStrategy;
public static T CurrentStrategy
{
get
{
if (currentStrategy == null)
currentStrategy = new T();
return currentStrategy;
}
}
}
然后:
public static void Main()
{
EntityMapper<ServerMappingStrategy>.CurrentStrategy.ToString();
EntityMapper<ClientMappingStrategy>.CurrentStrategy.ToString();
EntityMapper<ServerMappingStrategy>.CurrentStrategy.ToString();
}
嗯,问题是:
为什么我在调试时可以看到ServerBussinessMappingStrategy的构造函数只被调用一次?
这项工作很好,但我承认为什么总是EntityMapper返回我需要的正确实例,只是实例化一次ServerMappingStrategy类。
问候!
PD:对不起我的英文jeje;)答案 0 :(得分:5)
static
字段会在AppDomain
期间保留,并在首次创建时缓存:
public static T CurrentStrategy
{
get
{
if (currentStrategy == null) // <====== first use detected
currentStrategy = new T(); // <==== so create new and cache it
return currentStrategy; // <=========== return cached value
}
}
实际上,当它可以运行两次(或更多次)时会有一个边缘情况,但不太可能。
这是延迟初始化的一种非常常见的模式,并且在BCL的许多地方使用相同的模式。请注意,如果必须发生最多一次,则需要同步(lock
等)或类似带静态初始化程序的嵌套类。
答案 1 :(得分:1)
通常,它只会被调用一次。也就是说,除非你有竞争条件。
假设两个线程同时执行此语句:
EntityMapper<ServerMappingStrategy>.CurrentStrategy.ToString();
假设主题A 将在currentStrategy == null
之前运行,但在new T()
之前暂停,当Windows突然控制主题B 时会暂停再次进行比较,currentStrategy
仍为null,调用构造函数并将新实例分配给currentStrategy
。然后,在某些时候,Windows将控件返回到线程A ,再次调用构造函数。这很重要,因为通常静态成员(有点)预计是线程安全的。所以,如果我是你,我会将这一点包装成lock
条款。
P.S。这个片段不会编译,因为T可能是一个不能为null的结构。而不是比较为null,与default(T)比较或指定T必须是一个类。