I've written a class that implements IEnumerable<T>
. I have a method that returns MyClass
. If I try to yield return
from within that method, the compiler tells me "... cannot be an iterator block because ... is not an iterator interface type".
So, how can I define my own interface iterator type? Does it have to be "abstract" (can't have any methods defined)?
What I want to do is write a bunch of chainable methods, so every method should return an instance of MyClass
. But I need MyClass
to be some kind of enumerable. Rather than using some underlying data type, I was hoping I could just yield return
everywhere.
@Oded:
class SharpQuery : IEnumerable<HtmlNode>
{
public SharpQuery Find(string selector)
{
foreach (var n in this)
{
// filter the results
yield return node;
}
}
}
I think when you use yield return x
you will be producing an IEnumerable
of X type. So in your case it would be IEnumerable
Inheriting from one class would not automatically mean it will implicitly cast itself to that type. So if you write
class SharpQuery
{
public IEnumerable<HtmlNode> RepositoryItems { get; set; }
public IEnumerable<HtmlNode> Find(string selector)
{
foreach (var n in this.RepositoryItems)
{
// filter the results
yield return node;
}
}
}
it works. IEnumerable is not same as SharpQuery.
No, that's not possible. To see why consider that you have a class Zoo
that implements IEnumerable<Animal>
but also has lots of other members. A Zoo
is an IEnumerable<Animal>
but not necessarily vice versa - a sequence of animals is just a sequence of animals. There's no zoo keeper, no shops, no entrance fee or any of the other things that makes a zoo a zoo.
When you use yield return x
the return type cannot be Zoo
because you don't have a zoo - you just have a sequence of animals.
What you can do instead is to call it as new Zoo(foo())
where foo
returns an IEnumerable<Animal>
and add a constructor to Zoo
that accepts an IEnumerable<Animal>
.
According to section 8.2 of the C# Language Specification Version 4.0:
A block that contains one or more
yield
statements is called an iterator block. Iterator blocks are used to implement function members as iterators.
Section 10.14 specifies that the return type of an iterator must be one of the following:
IEnumerator
IEnumerable
IEnumerator<T>
IEnumerable<T>
According to section 10.14.4, invoking an iterator does not immediately execute the code in the iterator block. Instead, an enumerator object that implements the following interfaces is created and returned:
IEnumerator
IEnumerator<T>
IDisposable
The enumerator object is typically an instance of a compiler-generated nested class with private accessibility.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With