帮我理解c#中的代码片段

时间:2010-04-22 18:36:08

标签: c# code-snippets

我正在阅读此博客: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。

3 个答案:

答案 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>,因此情况可能并非如此,但在其他情况下可能是这样。