Задержка создания объекта

#c# #oop #class #object #constructor

#c# #ооп #класс #объект #конструктор

Вопрос:

Есть ли когда-нибудь случай, когда хранение необходимых данных для создания объекта и создание его только тогда, когда это абсолютно необходимо, лучше / эффективнее, чем хранение самого объекта?

Тривиальный пример:

 class Bar
{
    public string Data { get; set; }
}

class Foo
{
    Bar bar;
    readonly string barData;

    public Foo(string barData)
    {
        this.barData = barData;
    }

    public void MaybeCreate(bool create)
    {
        if (create)
        {
            bar = new Bar { Data = barData };
        }
    }

    public Bar Bar { get { return bar; } }
}
  

Комментарии:

1. До времени выполнения ничего не создается. 🙂

Ответ №1:

Это имеет смысл, если объект выполняет какую-то сложную операцию при построении, например, выделяет системные ресурсы.

Вы должны Lazy<T> помочь вам отложить создание экземпляра объекта. Помимо прочего, в него встроена потокобезопасность, если вам это нужно.

Комментарии:

1. 1 для Lazy<T> , что определенно имеет смысл в этой ситуации

Ответ №2:

В общем, нет. (Если я правильно понимаю ваш вопрос).

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

Комментарии:

1. Согласен. Не выполняйте слишком много работы в конструкторе. Гораздо лучше перепроектировать класс, у которого есть havy construtor. Следующая ссылка — рекомендация Google по этому поводу. Очень хорошее объяснение. misko.hevery.com/code-reviewers-guide /…

2. @gmamaladze — не уверен, как «тяжелые конструкторы» относятся к моему вопросу. Этот вопрос больше касается отложенной загрузки, чем создания гибких конструкторов… на самом деле, вы заметите, что конструктор Foo следует принципам, изложенным в вашей ссылке.

Ответ №3:

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

Например,

 List<int> ll = returnDataFromDBVeryVerySlowly();
  

или

 Lazy<List<int>> ll = new Lazy<List<int>>(() =>
{
    return returnDataFromDBVeryVerySlowly();
});
  

В первом примере returnDataFromDBVeryVerySlowly будет вызываться всегда, даже если вам это не нужно. Во втором он будет вызываться только в случае необходимости. Это довольно распространенное явление, например, в ASP.NET где вы хотите иметь «готовое» множество «стандартных» наборов данных, но вы не хотите, чтобы они заполнялись, если они не нужны, и вы хотите поместить их в качестве участников своей страницы, чтобы к ним могли обращаться несколько методов (в противном случае методможно было бы вызвать напрямую returnDataFromDBVeryVerySlowly )