C# 从泛型数组中获取泛型 IEnumerator

C# Obtaining a generic IEnumerator from a generic array

我正在使用最新版本的 Unity3D 和 MonoDevelop 使用 C#(我相信 Unity 目前使用的是 C# 版本 6,但我可能错了)。

我目前的情况是,我有一个二维数组的包装器 class,我希望能够像对常规二维数组一样使用 foreach 对其进行迭代.

public class CoordArray<T> : IEnumerable<T> {

    // ... some other members
    private T[,] arr;

    public CoordArray(int width, int height) {
        // ... other intialization
        arr = new T[height, width];
    }

    public IEnumerator<T> GetEnumerator() {
        return arr.GetEnumerator();
    }

    ...
}

public class Foo {
    public void Bar() {
        CoordArray<Poop> array = new CoordArray<Poop>(23,213);
        foreach(Poop p in array) DoSomething(p);
    }
}

然而,此 GetEnumerator() 方法在 Unity 中抛出以下错误:

Cannot implicitly convert type System.Collections.IEnumerator to System.Collections.Generic.IEnumerator<T>. An explicit conversion exists (are you missing a cast?)

我已经在这个网站上找到了一些类似问题的解决方案并且我已经尝试过:

public IEnumerator<T> GetEnumerator() {
    return ((IEnumerable<T>) arr).GetEnumerator();
}

但这又给我一个错误:

Cannot convert type T[,] to System.Collections.Generic.IEnumerable<T>

我也试过:

public IEnumerator<T> GetEnumerator() {
    return (IEnumerator<T>) arr.GetEnumerator();
}

,

public IEnumerator<T> GetEnumerator() {
    return arr.Cast<T>().GetEnumerator();
}

和:

public IEnumerator<T> GetEnumerator() {
    foreach (T element in arr) yield return element;
}

但是这些都抛出以下错误:

CoordArray<T> does not implement interface member System.Collections.IEnumerable.GetEnumerator() and the best implementing candidate CoordArray<T>.GetEnumerator() return type System.Collections.Generic.IEnumerator<T> does not match interface member return type System.Collections.IEnumerator

如果我尝试:

public IEnumerator GetEnumerator() {
    return arr.GetEnumerator();
}

抛出完全相反的错误:

CoordArray<T> does not implement interface member System.Collections.Generic.IEnumerable<T>.GetEnumerator() and the best implementing candidate CoordArray<T>.GetEnumerator() return type System.Collections.IEnumerator does not match interface member return type System.Collections.Generic.IEnumerator<T>

并且(很明显)它不会让我同时实现 IEnumerator GetEnumerator()IEnumerator<T> GetEnumerator()

有没有办法从通用数组中获取通用迭代器?

问题是二维数组只有 "implements" 非泛型 IEnumerable。但是你可以使用 Cast 方法获取 IEnumerable<T> 然后从中获取 IEnumerator<T>:

public IEnumerator<T> GetEnumerator()
{
    return arr.Cast<T>().GetEnumerator();
}

确保你已经包含

using System.Linq;

如果由于某种原因 Cast 方法不可用,那么我想至少你可以使用 C# 迭代器方法(自 2.0 起可用):

public IEnumerator<T> GetEnumerator()
{
    foreach (T element in arr)
        yield return element;
}

更新: 您遇到的新编译器错误有所不同。以上解决了通用 IEnumerable<T>.GetEnumerator() 方法的实现,我认为这是您问题的目标。但是由于 IEnumerable<T> 继承了 IEnumerable,您还需要在 class 中实现非泛型 GetEnumerator 方法(我假设您已经这样做了)。它需要明确实施,因此将以下内容添加到您的 class:

IEnumerator IEnumerable.GetEnumerator()
{
    return arr.GetEnumerator();
} 

这样的东西能满足您的需求吗?

public class CoordArray<T> : IEnumerable<T>
{

    // ... some other members
    private T[,] arr;

    public CoordArray(int width, int height)
    {
        // ... other intialization
        arr = new T[height, width];
    }

    private IEnumerable<T> ArrAsEnumerableT
    {
        get
        {
            foreach (var elmt in arr)
                yield return elmt;
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return ArrAsEnumerableT.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ArrAsEnumerableT.GetEnumerator();
    }
}