【问题标题】:Static and Generic working together .NET静态和通用一起工作 .NET
【发布时间】:2010-01-25 20:25:53
【问题描述】:

我有这个代码:

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

【问题讨论】:

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


    【解决方案1】:

    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 等)或类似带有静态初始化程序的嵌套类。

    【讨论】:

    【解决方案2】:

    通常,它只会被调用一次。也就是说,除非你有竞争条件。

    假设两个线程同时执行这条语句:

    EntityMapper<ServerMappingStrategy>.CurrentStrategy.ToString();
    

    假设 thread A 将一直运行到currentStrategy == null,但在new T() 之前暂停,此时 Windows 突然将控制权交给 thread B,然后再次进行比较, currentStrategy 仍然为 null,调用构造函数并将新实例分配给 currentStrategy。然后,在某个时候,Windows 将控制权交还给再次调用构造函数的线程 A。这很重要,因为通常静态成员(某种程度上)是线程安全的。因此,如果我是你,我会将这一点包装到 lock 子句中。

    附:这个 sn-p 不会编译,因为 T 可能是一个不能为空的结构。不要与 null 比较,而是与 default(T) 比较或指定 T 必须是一个类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-07
      • 2018-10-22
      • 2012-01-17
      • 2010-10-02
      • 2019-07-02
      • 1970-01-01
      • 1970-01-01
      • 2018-06-12
      相关资源
      最近更新 更多