我正在阅读这篇博客:管道和过滤器模式
我对这段代码感到困惑:
public class Pipeline<T>
{
private readonly List<IOperation<T>> operations = new List<IOperation<T>>();
public Pipeline<T> Register(IOperation<T> operation)
{
operations.Add(operation);
return this;
}
public void Execute()
{
IEnumerable<T> current = new List<T>();
foreach (IOperation<T> operation in operations)
{
current = operation.Execute(current);
}
IEnumerator<T> enumerator = current.GetEnumerator();
while (enumerator.MoveNext());
}
}
Run Code Online (Sandbox Code Playgroud)
这句话的目的是什么: while(enumerator.MoveNext()); ?似乎这个代码是noop.
首先考虑一下:
IEnumerable<T> current = new List<T>();
foreach (IOperation<T> operation in operations)
{
current = operation.Execute(current);
}
Run Code Online (Sandbox Code Playgroud)
此代码似乎是创建嵌套的枚举,每个枚举都使用前一个元素,对它们应用一些操作,并将结果传递给下一个.但它只构造了枚举.什么都没发生呢.它只是准备好了,存储在变量中current.有很多方法可以实现,IOperation.Execute但它可能是这样的.
IEnumerable<T> Execute(IEnumerable<T> ts)
{
foreach (T t in ts)
yield return this.operation(t); // Perform some operation on t.
}
Run Code Online (Sandbox Code Playgroud)
本文中建议的另一种选择是:
IEnumerable<T> Execute(IEnumerable<T> ts)
{
// Thank-you LINQ!
// This was 10 lines of non-LINQ code in the original article.
return ts.OrderBy(t => t.Foo);
}
Run Code Online (Sandbox Code Playgroud)
现在看看这个:
IEnumerator<T> enumerator = current.GetEnumerator();
while (enumerator.MoveNext());
Run Code Online (Sandbox Code Playgroud)
这实际上导致执行操作链.当从枚举中请求元素时,它会使原始可枚举中的元素通过链传递IOperations,每个元素对它们执行一些操作.最终结果被丢弃,因此只有操作的副作用很有趣 - 例如写入控制台或记录到文件.这可能是编写最后两行的简单方法:
foreach (T t in current) {}
Run Code Online (Sandbox Code Playgroud)
另一件需要注意的事情是,启动进程的初始列表是一个空列表,因此为了理解这一点,必须在第一个操作中创建一些T实例.在本文中,这是通过询问用户从控制台输入来完成的.