【问题标题】:C#: Custom IEnumerator?C#:自定义 IEnumerator?
【发布时间】:2015-12-02 23:24:06
【问题描述】:

这是与 Unity 中的 C# 相关的消息,但我假设一般 C# 知识将适用。

取以下代码:

class myClass
{
    IEnumerator myEnumerator;
    public IEnumerator theEnumerator()
    {
        int i = 0;
        while (true)
        {
            Debug.Log(i++);
            yield return null;
        }
    }

    public void Update()
    {
        if (myEnumerator == null) { myEnumerator = theEnumerator(); }
        myEnumerator.MoveNext();
    }
}

如果我实例化该类,然后每帧调用一次“更新”,我会在日志中得到以下输出:

0
1
2
3
4...

这很好用,但是我想在 IEnumerator 本身中实现一些自定义功能。但如果我创建以下内容:

public class myIEnumerator : IEnumerator
{
    public int myCustValue;
    public void myCustFunction(){}
}

然后更新 oringal 类,将“IEnumerator”替换为“myIEnumerator”,出现以下错误:

The body of `myClass.theEnumerator()' cannot be an iterator block because `myIEnumerator ' is not an iterator interface type

我在这里做错了什么,如何制作自己的自定义 IEnumerator?

【问题讨论】:

  • 我认为这是编译器的问题,编译器仅支持IEnumerableIEnumerable<T>IEnumeratorIEnumerator<T>。继承不适用于迭代器块。
  • docs, "Iterator Methods and get Accessors 迭代器的声明必须满足以下要求:返回类型必须是 IEnumerable、IEnumerable、IEnumerator 或 IEnumerator. 声明不能有任何 ref 或 out 参数。”

标签: c# ienumerator


【解决方案1】:

您只能在返回类型为IEnumeratorIEnumerableIEnumerator<T>IEnumerable<T> 的方法中使用yield。您不能将方法的返回类型更改为实现这些接口之一的类型,这是没有意义的。

原因是 C# 编译器生成了一个特殊的类,它实现了这 4 个接口之一(实际上它同时实现了 IEnumeratorIEnumerable 或其通用版本),并且该编译器生成的类的实例是实际从该方法返回的内容。通过更改返回类型,您试图说编译器将创建您的类的一个实例来进行枚举。但它不能这样做,因为它实际上对你的班级一无所知(事实上你的班级甚至可能无法正确枚举)。

【讨论】:

  • 啊,有道理。谢谢你的解释!
【解决方案2】:

我不熟悉 Unity,但我认为您必须实现 IEnumerator 接口。方法 MoveNext()Reset() 缺失。

看看IEnumerator Interface

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-07
    • 2010-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2020-12-29
    • 2016-08-24
    相关资源
    最近更新 更多