12

在 Rob Conery 的 Storefront 系列中,Rob 广泛使用该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>();
4

1 回答 1

17

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<T> 适用于当您希望 IQueryable<T> 的结果作为 List<T> 的特定用例,但您不希望在使用它之前进行评估。


更新以回答扩展问题:

如果我想将 IQueryable 作为 List<T> 进行操作,您会推荐其中一个吗?我假设由于 Lazy<T> 现在在框架中,对于未来的支持和可维护性来说这是一个更安全的选择?

我个人也不会使用。如果您有 IQueryable,我会将其保留为 IQueryable,以最大限度地提高您的灵活性。通过保留 IQueryable,您仍然可以访问 LINQ to SQL 的查询理解(只要上下文仍然存在)。

例如,如果您在 IQueryable 上调用 .ToList() ,您是在要求 LINQ to SQL 从目标表中选择所有列并混合所有结果(这可能非常昂贵,特别是如果您有数千个结果)。这将被翻译成类似“SELECT * FROM MyTable”的内容。

如果您在 IQueryable 上调用 .Count(),则您要求 LINQ to SQL 仅获取结果数,这将被转换为“SELECT COUNT(*) FROM MyTable”之类的内容。这样做比将所有结果水合然后计算它们更有效,特别是如果您只对数字感兴趣!

通过在 IQueryable LINQ to SQL 上使用 .Where() 会将您的条件添加到 SQL 查询中的 WHERE 子句中。这意味着您只会从您感兴趣的 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>> 是包含 List<Product> 的包装器。因为您对在惰性评估列表上进行操作特别感兴趣,所以我想说 LazyList可能更适合您的目的。

你应该问问自己是否真的需要一份实际的产品清单。如果没有令人信服的理由拥有一个实际的列表,我会坚持使用 IQueryable。

于 2010-04-22T11:27:17.103 回答