我正在阅读此博客:Pipes and filters pattern
我对此代码段感到困惑:
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());
}
}
此声明的目的是什么: while(enumerator.MoveNext()); ?看来这段代码是noop。
答案 0 :(得分:7)
首先考虑一下:
IEnumerable<T> current = new List<T>();
foreach (IOperation<T> operation in operations)
{
current = operation.Execute(current);
}
此代码似乎是创建嵌套的枚举,每个枚举都使用前一个元素,对它们应用一些操作,并将结果传递给下一个。但它只构造了枚举。什么都没发生呢。它已准备就绪,存储在变量current
中。有很多方法可以实现IOperation.Execute
,但它可能是这样的。
IEnumerable<T> Execute(IEnumerable<T> ts)
{
foreach (T t in ts)
yield return this.operation(t); // Perform some operation on t.
}
文章中建议的另一个选项是:
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);
}
现在看看:
IEnumerator<T> enumerator = current.GetEnumerator();
while (enumerator.MoveNext());
这实际上导致执行操作链。当从枚举中请求元素时,它会使原始可枚举的元素通过IOperations
链传递,每个链都对它们执行一些操作。最终结果被丢弃,因此只有操作的副作用很有趣 - 例如写入控制台或记录到文件。这可能是编写最后两行的简单方法:
foreach (T t in current) {}
另一件需要注意的事情是,启动进程的初始列表是一个空列表,因此为了理解,必须在第一个操作中创建一些T实例。在本文中,这是通过询问用户从控制台输入来完成的。
答案 1 :(得分:3)
在这种情况下,while (enumerator.MoveNext());
只是评估最终IOperation<T>
返回的所有项目。它看起来有点令人困惑,但只创建空List<T>
以便为第一个IOperation<T>
提供值。
在许多集合中,这会像你建议的那样做得很多,但鉴于我们讨论的是管道和过滤器模式,最终的值可能是某种迭代器会导致代码被执行。它可能是这样的,例如(假设它是一个整数):
public class WriteToConsoleOperation : IOperation<int>
{
public IEnumerable<int> Execute(IEnumerable<int> ints)
{
foreach (var i in ints)
{
Console.WriteLine(i);
yield return i;
}
}
}
因此,对此迭代器返回的MoveNext()
上的每个项调用IEnumerator<int>
将返回每个值(在while
循环中被忽略),但也会输出每个值到控制台。
这有意义吗?
答案 2 :(得分:1)
while (enumerator.MoveNext());
在当前代码块中,没有任何影响(它遍历枚举中的所有项)。显示的代码不会对枚举中的当前元素起作用。可能发生的事情是MoveNext()方法正在移动到下一个元素,它正在对集合中的对象执行某些操作(更新内部值,从数据库中提取下一个等)。由于类型为List<T>
,因此情况可能并非如此,但在其他情况下可能是这样。