Что такое ленивое создание экземпляров

Является ли ленивая реализация меньшим количеством кода, но с тем же результатом? Конечно, это, как правило, хорошая вещь (при условии, что код будет коротким/эффективным, что не повредит читабельности/обслуживаемости).

Пожалуйста, обратитесь к этому ленивому экземпляру:

public sealed class Singleton
{
    private Singleton()
    {
    }

    public static Singleton Instance { get { return Nested.instance; } }

    private class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
} 

Нет частного свойства Instance (я знаю, что оно неявное) - это то, что делает его ленивым - тот факт, что у нас нет сеттера в свойстве public static Singleton Instance?


person Dave    schedule 25.09.2012    source источник
comment
msdn.microsoft.com/en-us/library/dd997286.aspx   -  person user981225    schedule 25.09.2012
comment
Почему бы вам не использовать Lazy<T>? взгляните на эту статью: msdn: отложенная инициализация   -  person Tim Schmelter    schedule 25.09.2012
comment
Я читал это - проблема в том, что я не понимаю без тестирования, а на работе мы только на .Net 2.0 (поэтому я не могу использовать ‹T›) - Не спрашивайте!!   -  person Dave    schedule 25.09.2012
comment
@DaveRook: вот Lazy<Singleton>: stackoverflow.com/a/6847882/284240   -  person Tim Schmelter    schedule 25.09.2012


Ответы (5)


Допустим, у нас есть поле типа, создание которого требует больших затрат.

class Foo
{
    public readonly Expensive expensive = new Expensive();
    ...
}

Проблема с этим кодом заключается в том, что создание экземпляра Foo влечет за собой затраты производительности на создание экземпляра Expensive независимо от того, был ли когда-либо осуществлен доступ к полю Expensive. Очевидный ответ — создать экземпляр по запросу или лениво создать экземпляр поля:

class Foo
{
    Expensive _expensive;
    public Expensive
    {
        get
        {
            if (_expensive == null) _expensive = new Expensive();
            return _expensive;
        }
    }
    ...
}

Это ленивое воплощение.

person MoonKnight    schedule 25.09.2012
comment
Вы предлагаете также сделать каждое поле ленивой загрузкой (при условии, что свойство является классом) - person Dave; 25.09.2012
comment
Не было бы смысла лениво создавать что-либо, что не было бы затратным для инициализации. В этом весь смысл. Вы можете сделать это с любым классом, который вы хотите, используя метод доступа таким образом. - person MoonKnight; 25.09.2012
comment
На мой вопрос есть несколько хороших ответов, но это действительно заставило меня задуматься о других способах его реализации. Хотя, может быть, проще думать об этом как об эффективной загрузке, а не о ленивой загрузке! :) - person Dave; 25.09.2012

Ленивая инициализация — это практика, при которой вы загружаете или инициализируете объект только когда он вам впервые понадобится.

Потенциально это может значительно повысить производительность, особенно если в вашем приложении имеется большое количество компонентов.

Загляните на страницу Википедии, чтобы получить больше информации (там есть закодированные примеры).

person dsgriffin    schedule 25.09.2012
comment
Я видел эту вики-страницу, но ленивая загрузка, ленивая инициализация и ленивая оценка, нетерпеливая инициализация и т. д. заставили меня подумать (на этом раннем этапе моего обучения), что все они разные. Я начинаю понимать, что ленивый init. / ленивая загрузка — это одно и то же - person Dave; 25.09.2012
comment
Ну, это семантика. Это может означать разные вещи. Класс может быть лениво инициализирован, но, возможно, класс также лениво загружает медиаданные. - person Kache; 25.09.2012

Нет, ленивое создание экземпляров означает, что вы не тратите время и ресурсы на создание чего-либо, пока оно вам на самом деле не понадобится.

В вашем примере с синглтоном instance - это просто пустая ссылка, пока она не будет фактически использована. Когда он используется, затем вы тратите ресурсы на создание экземпляра объекта с помощью new.

person Kache    schedule 25.09.2012
comment
Ах, отсюда и тот факт, что он находится в статическом методе - вызывайте его только тогда, когда это необходимо, без каких-либо предварительных действий! - person Dave; 25.09.2012
comment
Да. Также для синглтона будущие вызовы будут просто обращаться к этому уже созданному экземпляру. - person Kache; 25.09.2012
comment
Да, теперь я знаю о синглтоне! Это был тип загрузки, который я не получил, спасибо. - person Dave; 25.09.2012

Отложенная инициализация объекта означает, что его создание откладывается до первого использования.

Полную информацию см. в сообщении msdn Отложенная инициализация

В приведенном выше коде экземпляр класса singleton не создается до тех пор, пока вы его не вызовете. Таким образом, ваша программа не будет использовать ресурсы, пока не будет вызван ваш код.

person Kishore Kumar    schedule 25.09.2012

Это лениво, потому что экземпляр класса Singleton не создается до тех пор, пока вы не попросите его в первый раз.

person James Cronen    schedule 25.09.2012