LazyList <T>vs System.Lazy <List <T>> в ASP.NET MVC 2? - PullRequest
12 голосов
/ 22 апреля 2010

В серии Storefront Роба Конери Роб широко использует конструкцию LazyList<..> для извлечения данных из IQueryables.

  • Чем это отличается от конструкции System.Lazy<...>, доступной в .NET 4.0 (и, возможно, ранее)?

Больше глубины, основываясь на великолепном ответе DoctaJones:

  1. Вы бы порекомендовали одно поверх другого, если бы я хотел оперировать на IQueryable как List<T>?
    Я предполагаю, что, поскольку Lazy<T> находится в структуре сейчас, это более безопасная ставка для будущей поддержки и ремонтопригодности?
  2. Если я хочу использовать строгий тип вместо анонимного (var), будут ли следующие утверждения функционально эквивалентны?
    • Lazy<List<Products>> Products = new Lazy<List<Product>>();
    • LazyList<Product> = new LazyList<Product>();

1 Ответ

17 голосов
/ 22 апреля 2010

LasyList работает только с источником IQueryable . Это реализация IList , которая работает путем заполнения частного списка всеми результатами из указанного IQueryable . Инициализация происходит при первом обращении к любому из членов IList .

Пример использования будет

var myList = new LazyList(products.Where(p => p.Name.StartsWith("T"));
//initialization occurs here
Console.Write(myList.Count);

Класс System.Lazy работает с любым типом и не ограничивается IQueryable . Ленивая инициализация происходит при первом обращении к свойству Lazy .Value .

Пример использования будет

var lazyString = new Lazy(() => "Hello world");
//initialization occurs here
Console.Write(lazyString.Value);

Мы могли бы переписать пример LazyList для использования Lazy следующим образом:

var myList = new Lazy(() => products.Where(p => p.Name.StartsWith("T").ToList());
//initialization occurs here
Console.Write(myList.Value.Count);

Вкратце: LazyList работает только с IQueryable , Lazy работает с любым типом.

LazyList предназначен для конкретного случая использования, когда вы хотите, чтобы результаты IQueryable представляли собой список , но вы не хотите, чтобы оценка производилась до тех пор, пока вы ее не используете.


ОБНОВЛЕНИЕ, чтобы ответить на расширенный вопрос:

Вы бы порекомендовали одно поверх другого, если бы я хотел работать с IQueryable в виде списка ? Я предполагаю, что, поскольку Lazy находится в структуре сейчас, это более безопасная ставка для будущей поддержки и ремонтопригодности?

Лично я бы тоже не использовал. Если у вас есть IQueryable, я бы сохранил его как IQueryable, чтобы максимизировать вашу гибкость. Сохраняя IQueryable, вы по-прежнему получаете доступ к LINQ для понимания запросов SQL (пока контекст еще жив).

Например, если вы вызываете .ToList () для IQueryable, вы просите LINQ to SQL выбрать все столбцов из целевой таблицы и гидрировать все результатов (это может быть очень дорого, особенно если у вас есть тысячи результатов). Это будет переведено в нечто вроде «SELECT * FROM MyTable».

Если вы вызываете .Count () в IQueryable, вы запрашиваете LINQ to SQL, чтобы просто получить количество результатов, это будет преобразовано в нечто вроде «SELECT COUNT (*) FROM MyTable». Делать это гораздо эффективнее, чем увлажнять все результаты, а затем подсчитывать их, особенно если вас интересует только число!

Использование .Where () в IQueryable LINQ to SQL добавит ваши условия к предложению WHERE в запросе SQL. Это означает, что вы будете извлекать данные только из интересующего вас SQL-кода, а не гидрировать результаты, которые вы не собираетесь использовать.

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

Если я хочу использовать сильный тип вместо анонимного (var) типа, будут ли следующие операторы функционально эквивалентными?

Lazy<List<Product>> products = new Lazy<List<Product>>(); 
LazyList<Product> products = new LazyList<Product>();

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

Два утверждения не являются функционально эквивалентными. LazyList - это IList , тогда как Lazy > - это оболочка, содержащая List . Поскольку вы особенно заинтересованы в работе с отложенным оценочным списком, я бы сказал, что LazyList , вероятно, более конкретен для ваших целей.

Вы должны спросить себя, действительно ли вам нужен фактический Список продуктов. Если у меня нет веских причин для создания настоящего Списка, я бы придерживался IQueryable.

...