Why can't I use OrderBy even though GetEnumerator and foreach work well?

I applied the method GetEnumerator

for a simple class and was surprised that I could not order an enum from linq (the call is this.OrderBy(x => x)

invalid). Can someone please explain what's going on here? Am I doing something wrong or are listed for review only?

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


source to share


3 answers


You have to implement the interface IEnumerable<int>

in order for it to this.OrderBy

work, how else does it need to know this

can enumerate int

s?

OrderBy

requires to this

implement IEnumerable<T>

. He doesn't know that your method GetEnumerator

is actually an attempt to execute an interface.



foreach

it just requires a method GetEnumerator()

, no interface implementation is required.

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

      

+7


source


OrderBy()

is an extension method on IEnumerable<T>

.
Your class doesn't implement IEnumerable<T>

.

foreach

still works because it doesn't require execution IEnumerable<T>

; it only requires a method GetEnumerator()

.

So, all you have to do is add:



class Test : IEnumerable<int>

      

and provide an implementation for not generic IEnumerable

:

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

      

+1


source


An enumerator is an iterator. It's just an interface that tells the current or user code how to go to the next element in some sequence, reset the iteration to the first element again, or get the current element in the iteration.

That is, the enumerator is not listable. An enumerator can create an enumerator so that other code can enumerate the enumeration.

To be able to call a LINQ extension method, you need the object to be enumerable. Your class Test

doesn't implement IEnumerable<T>

(LINQ extension type signatures look like this :) public static IEnumerable<T> Whatever<T>(this IEnumerable<T> someEnumerable)

.

Since I want to apply the DRY principle on myself (don't repeat myself), if you want to know how to implement IEnumerable<T>

, you should look at the following questions and answers: How to implement IEnumerable <T> .

+1


source







All Articles