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

时间:2015-07-09 13:32:12

标签: c# linq enumerator

我为一个简单的类实现了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]);
    }
}

3 个答案:

答案 0 :(得分:7)

您必须实现界面IEnumerable<int>才能使this.OrderBy正常工作,知道this如何能够枚举int

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();
    }
}

答案 1 :(得分:1)

OrderBy()IEnumerable<T>的扩展方法 您的课程没有实施IEnumerable<T>

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

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

class Test : IEnumerable<int>

并提供非通用IEnumerable的实现:

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

答案 2 :(得分:1)

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

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

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

由于我想对自己应用DRY原则(不要重复自己),如果你想知道如何实施IEnumerable<T>,你应该看看下面的问答:How do I implement IEnumerable<T>。< / p>