【问题标题】:Why I can't use OrderBy despite having GetEnumerator and foreach working well?尽管 GetEnumerator 和 foreach 运行良好,为什么我不能使用 OrderBy?
【发布时间】:2015-07-09 13:32:11
【问题描述】:

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

【问题讨论】:

标签: c# linq enumerator


【解决方案1】:

您必须实现接口IEnumerable&lt;int&gt; 才能使this.OrderBy 工作,否则它怎么知道this 可以枚举ints?

OrderBy 需要this 来实现IEnumerable&lt;T&gt;。它不知道你的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();
    }
}

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

      OrderBy()IEnumerable&lt;T&gt; 的扩展方法。
      你的类没有实现IEnumerable&lt;T&gt;

      foreach 仍然有效,因为它不需要你实现IEnumerable&lt;T&gt;;它只要求有一个方法GetEnumerator()

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

      class Test : IEnumerable<int>
      

      并提供非泛型IEnumerable的实现:

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

      【讨论】:

        猜你喜欢
        • 2021-03-13
        • 1970-01-01
        • 1970-01-01
        • 2021-06-21
        • 2020-05-19
        • 2013-07-14
        • 1970-01-01
        • 2020-08-02
        • 1970-01-01
        相关资源
        最近更新 更多