有没有在生成的迭代器块中获得对“this”的引用的方法?

时间:2011-07-12 21:00:26

标签: c# iterator extension-methods

从C#2.0开始,我们已经能够在类中声明迭代器块并使用yield return关键字从它们返回值。在幕后,编译器慷慨地将我们相当简单的迭代器块转换为它自己的类,一个完全实现IEnumerableIEnumerator接口的状态机。使用ILSpy或Reflector,您可以了解这些类的外观。

在C#3.5中,扩展方法被添加到语言中,提供了一种编写静态方法的简单方法,这些方法将出现在现有类或接口的intellisense弹出窗口中。

我感兴趣的是将这两个概念结合起来,这样做我遇到了困难。我的挫败感在于,在迭代器块中,this关键字指的是迭代器块所在的类,而不是包含迭代器块实现的编译器生成的类。

我想做的是这样的事情:

public static class IteratorExtensions
{
    public static void DoSomething<T>(this IEnumerable<T> iterator)
    {
        Console.WriteLine("Running iterator block of type :" + typeof(T).Name);
    }
}

public class IteratorExample
{
    public IEnumerable<string> MyIterator()
    {
        yield return "Hello";
        this.DoSomething();
        yield return "World";
    }
}

不幸的是,在此上下文中,this引用了IteratorExample的实例,而不是生成的MyIterator类的实例。有没有办法在迭代器中获取引用,还是我必须重新考虑我的计划?

3 个答案:

答案 0 :(得分:3)

没有干净的方式,没有。所有this用法都被截获,并引用声明实例。

你可以可能做一些涉及滥用堆栈或类似事件的可怕事情,但没有什么是整洁的。您可以链接迭代器LINQ风格吗?即。

public static IEnumerable<T> WithLogging<T>(this IEnumerable<T> source)
{
    source.DoSomething();
    try {
        foreach(var item in source) yield return item;
    } finally {
        source.DoSomethingElse();
    }
}

并使用originalIterator.WithLogging()

答案 1 :(得分:0)

我认为你不能做你想做的事情 - 我认为语言规范隐藏了实现类,所以它不会限制可能使用不同机制的同一特性的未来实现。 / p>

答案 2 :(得分:0)

这不起作用,所以你必须重新考虑你的计划。

如果您提供有关您希望实现的目标的更多信息,我们可能会帮助您找到替代解决方案。