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]);
}
}
source to share
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();
}
}
source to share
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();
}
source to share
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> .
source to share