延迟执行中装饰器序列的用途是什么?

时间:2014-01-07 01:46:44

标签: c# .net linq decorator lazy-evaluation

我正在学习LINQ,并试图理解延迟执行是如何工作的?

困扰我的单行是: -

  

查询运算符通过返回装饰器序列来提供延迟执行。

我试过搜索装饰器,我得到的信息是: -

  

装饰器动态地将附加职责附加到对象。装饰器为子类化提供了灵活的替代扩展功能。

我无法在执行LINQ(延迟执行)和装饰器角色的情况下建立任何链接。

因此,我只想知道装饰器/装饰器序列在LINQ的延迟执行中的作用。

2 个答案:

答案 0 :(得分:3)

这是decorator design pattern的经典应用。

让我们将the class diagram from wikipedia article“映射”到LINQ的一个方法,并在下面执行延迟执行:

vat list = new List<int> {1, 2, 3, 4, 5, 6, 7};
var res = list.Take(3);
  • ComponentIEnumerable<T>
  • ConcreteComponentList<T>
  • ConcreteDecorator是一个实现IEnumerable<T>方法返回Take(int)的类。该实现引用了Component(在我们的例子中,它是ConcreteComponent,但它也可以是一个抽象组件。)

但请注意,ConcreteDecorator (或不总是)手动编写。相反,当实现使用yield return语句时,通常为generated by the C# compiler

答案 1 :(得分:1)

我不会回答所使用的实际术语,但要明白的是,LINQ to Objects是使用迭代器块有效实现的(无论这是否与实际实现有些无关)。例如,忽略参数验证,请考虑Where

public static IEnumerable<T> Where(this IEnumerable<T> source,
                                   Func<T, bool> predicate)
{
    // TODO: Eager argument validation (not as easy as it sounds)
    foreach (var item in source)
    {
        if (predicate(item))
        {
            yield return item;
        }
    }
}

重要的是,当序列返回被要求提供下一个元素时,此代码仅询问原始输入源的数据。这是你的延期执行。实际上,此方法的 none 会一直执行,直到调用者要求调用GetEnumerator()然后调用MoveNext()

这是一个装饰器,返回的序列有效地记住了对原始序列的引用,并且只是在它进行时对其进行转换,而不是立即获取所有项目。

有关详细信息,请参阅: