尽管 GetEnumerator 和 foreach 运行良好,但为什么我不能使用 OrderBy?

Why I can't use OrderBy despite having GetEnumerator and foreach working well?

我已经为一个简单的 class 实现了 GetEnumerator 方法,令我惊讶的是我无法使用 linq 对枚举器进行排序(对 this.OrderBy(x => x) 的调用无效)。有人可以解释一下这里发生了什么吗?我是在做错什么还是枚举数只是为了迭代?

class Test
{
    private Dictionary<int, string> dict
        = new Dictionary<int, string>();

    public IEnumerator<int> GetEnumerator()
    {
        return dict.Keys.GetEnumerator();
    }

    public Test()
    {
        dict[1] = "test";
        dict[2] = "nothing";
    }

    public IEnumerable<int> SortedKeys
    {
        get { return this.OrderBy(x => x); } // illegal!
    }

    public void Print()
    {
        foreach(var key in this)
            Console.WriteLine(dict[key]);
    }
}

您必须实现接口 IEnumerable<int> 才能让 this.OrderBy 工作,否则它怎么知道 this 可以枚举 ints?

OrderBy 需要 this 来实现 IEnumerable<T>。它不知道您的 GetEnumerator 方法实际上是试图遵守接口。

foreach只需要一个GetEnumerator()方法,不需要接口实现。

// put in the interface
class Test : IEnumerable<int>
{
    private Dictionary<int, string> dict
        = new Dictionary<int, string>();

    public IEnumerator<int> GetEnumerator()
    {
        return dict.Keys.GetEnumerator();
    }

    public Test()
    {
        dict[1] = "test";
        dict[2] = "nothing";
    }

    public IEnumerable<int> SortedKeys
    {
        get { return this.OrderBy(x => x); } // illegal!
    }

    public void Print()
    {
        foreach (var key in this)
            Console.WriteLine(dict[key]);
    }

    // this one is required according to the interface too
    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

OrderBy()IEnumerable<T> 上的扩展方法。
您的 class 没有实现 IEnumerable<T>.

foreach 仍然有效,因为它不需要您实施 IEnumerable<T>;它只需要有一个方法 GetEnumerator().

所以你需要做的就是添加:

class Test : IEnumerable<int>

并提供非泛型的实现 IEnumerable:

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

枚举器是迭代器。它只是一个接口,告诉运行时或自定义代码如何移动到某个序列中的下一个元素、再次将迭代重置为第一个元素或获取迭代中的当前元素。

也就是说,枚举数是不可枚举的。可枚举可以创建一个枚举器让其他代码枚举枚举。

为了能够调用 LINQ 扩展方法,您需要对象 是可枚举的。您的 Test class 未实现 IEnumerable<T>(LINQ 扩展方法签名如下所示:public static IEnumerable<T> Whatever<T>(this IEnumerable<T> someEnumerable))。

因为我想对自己应用DRY原则(Don't Repeat Yourself),如果你想知道如何实现IEnumerable<T>你应该看看下面的问答:How do I implement IEnumerable<T>