静态和通用协同工作.NET

时间:2010-01-25 20:25:53

标签: c# .net entity-framework static generics

我有这段代码:

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;)

2 个答案:

答案 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必须是一个类。