Static и Generic работают вместе .NET - PullRequest
0 голосов
/ 25 января 2010

У меня есть этот код:

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.

Привет! * * 1013

PD: Извините, мой английский jeje;)

Ответы [ 2 ]

5 голосов
/ 25 января 2010

Поле 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 голос
/ 25 января 2010

Обычно он вызывается только один раз. То есть, если у вас нет состояния гонки.

Допустим, два потока выполняют этот оператор одновременно:

EntityMapper<ServerMappingStrategy>.CurrentStrategy.ToString();

Допустим, поток A будет работать до currentStrategy == null, но останавливается до new T(), когда Windows внезапно передает управление потоку B , который затем снова выполняет сравнение currentStrategy по-прежнему равен нулю, вызывает конструктор и присваивает новый экземпляр currentStrategy. Затем в какой-то момент Windows возвращает элемент управления потоку A , который снова вызывает конструктор. Это важно, потому что обычно статические члены (как бы) должны быть потокобезопасными. Так что на вашем месте я бы обернул этот бит в lock предложение.

P.S. этот фрагмент не будет компилироваться, так как T может быть структурой, которая не может быть нулевой. Вместо сравнения с нулем сравните со значением по умолчанию (T) или укажите, что T должен быть классом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...