Pull to refresh

Lazy<T>: конструирование объектов по требованию в .NET 4.0

Reading time 2 min
Views 16K
Original author: Bill Wagner
Мне нравится, когда я нахожу новые части функциональности в .NET framework. Это все те большие интересности, которые получают всю любовь и признание на конференциях и в журналах.

Lazy<T> как раз один из таких.

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

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

Lazy<ExpensiveResource> ownedResource = new Lazy<ExpensiveResource>();

Вы можете просто сослаться на "ownedResource.Value" чтобы добраться до этого дорогостоящего объекта. В первый раз когда вы обращаетесь к ownedResource.Value, выделяются доростоящие ресурсы, но не ранее.

Lazy<T> также имеет булевое свойство, называющееся IsValueCreated, которое вы можете проверить чтобы увидеть был ли создан объект в свойстве Value. Это может оказаться полезным когда вам нужно хранить информацию из дорогостоящего ресурса, но только если она будет использована.

Поддержка типов без конструкторов по умолчанию


Lazy<T> не навязывает ограничение на наличие new(). Вы можете использовать Lazy<T> для типов, которые должны быть созданы с помощью других конструкторов и даже фабричных методов. Второй конструктор определяет делегат Func<T> который возвращает новый дорогостоящий ресурс:

Lazy<ExpensiveResource> ownedResource = new Lazy<ExpensiveResource>(
   () => new ExpensiveResource("filename.data"));


 Вы можете использовать этот конструктор для лучшего контроля того, как код создаст дорогостоящий ресурс. Здесь я использовал другой конструктор, но вы можете использовать фабричный метод, контейнер IoC или другой метод.

Мы живем в многоядерном мире


Lazy<T> имеет еще два конструктора:

public Lazy(bool isThreadSafe);
public Lazy(Func<T> valueFactory, bool isThreadSafe);


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

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

Я рад, что это было добавлено.

Tags: C#, .NET General, C# General, DevCenterPosts
Tags:
Hubs:
+22
Comments 31
Comments Comments 31

Articles