Подтвердить что ты не робот

LazyList <T> vs System.Lazy <List <T>> в ASP.NET MVC 2?

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

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

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

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

Ответ 1

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

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

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

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

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

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

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

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

Короче: LazyList <T> работает только с IQueryable <T> , Lazy <T> работает с любым типом.

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


ОБНОВЛЕНИЕ для ответа на расширенный вопрос:

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

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

Например, если вы вызываете .ToList() в IQueryable, вы запрашиваете LINQ to SQL для выбора all столбцов из целевой таблицы и гидратации всех результаты (это может быть очень дорого, особенно если у вас есть тысячи результатов). Это будет переведено на нечто вроде "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 <Product> является IList <Product> , где Lazy < List <Product → > представляет собой оболочку, содержащую список <Product> . Поскольку вы особенно заинтересованы в работе с ленивым оценочным списком, я бы сказал, что LazyList, вероятно, более определен для ваших целей.

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