Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

yield method

Status
Not open for further replies.

kav123

Programmer
Jan 12, 2005
210
GB
Could anyone explain me how the yield method works?? When we use this method, is it true that we do not need to implement the IEnumerable/IEnumerator interface for that class.
 
No, the yield-statement helps you to implement IEnumerable, without having to build Enumerator-classes.
You can use it if you need read-only collection-like functionality - only enable foreach.
However, if you combine with Linq, there are lots of extra possiblities for the consumer.

example:
Code:
public IEnumerable<Foo> GetFooWithBar()
{ 
  foreach(Foo foo in _myFooList)
  {
    if(foo.IsBarrable)
    {
      foo.Bar = BarRepository.RetrieveBar(foo.Id);
      yield return foo;
    }
  }
}
There are some caveats:
- Everytime you iterate through GetFooWithBar() the the code executes, so in this example you would make lots of calls on the repository if you make more calls on this method.
- The code is executed when you start to iterate. So:
Code:
IEnumerable<Foo> mylist = ThatOtherClass.GetFooWithBar();
does not call the repository - in fact is does nothing.
However, later on:
Code:
foreach(Foo foo in mylist)
{
  DoSomeStuff();
}
will exececute as if you wrote:
Code:
foreach(Foo foo in ThatOtherClass._myFooList)
{
  if(foo.IsBarrable)
  {
    foo.Bar = BarRepository.RetrieveBar(foo.Id);
    DoSomeStuff();
  }
}

My, this is harder to explain then I thought it would be...
If you write so testcode and set some breakpoints, it will be much clearer.

 
Hello, Actually i am just getting myself familiar with yield method. It is something which i think i might find very useful in my next project. I came across this in a book. In the example, basically i noticed that when the yield method was being used, the class did not implement the IEnumerble interface. All it did was, the GetEnumerator method, returned IEnumerator something like

public IEnumerator GetEnumerator()
{
foreach(a in collection)
{
yield return a;
}

}

I am just trying to figure out, what are the advantages of it??
 
The code in your example has no advantage - you could just return the collection, or the enumerator of the collection.
However, as soon as want to do something with the items in the collection before returning them, you either have to build an enumerator-class, or use the construction with the yield-statement.
You might even create new types on the fly:
Code:
public IEnumemerable<PersonAdress> GetPersonAdresses()
{
  foreach(Person person in _personsList)
  {
    Adress adress = getAdres(person.Id);
    yield return new PersonAdress(person, adress);
  }
}
Another advantage could be that because of the delayed execution only one item has to be in memory. In the example I posted the variable mylist does not actually contain any items, it is not a copy of the items in _myFooList. It only gets one item per iterator-step.

 
(sorry for using the term 'new types', I meant you could create instances of another type then your original items)
 
O, I forgot to mention this:
Code:
public IEnumerable<Person> AllPersonsInClass
{
  foreach(Person p in _studens)
  {
    yield return p;
  }
  foreach(Person p in _teachers)
  {
    yield return p;
  }
  yield return _janitor;
}
 
So basically does this mean that you do not need to implement the IEnumerator in your class. yield does it for you, and it also helps create instances of custom types on the fly...??
 
yield is a keyword for IEnumerable (or IEnumerable<T>) any object which implmements IEnumerable can use the yeild to iterate.

the advantage is the method does not execute until the collection is enumerated.
for example

Code:
IEnumerable<int> numbers = GetNumbers();

private IEnumerable<int> GetNumbers()
{
   for(i = 0;i<100;i++) yield return i;
}
will not be called.
however this could call GetNumbers()
Code:
IEnumerable<int> numbers = new List<int>(GetNumbers());

private IEnumerable<int> GetNumbers()
{
   for(i = 0;i<100;i++) yield return i;
}
or
Code:
foreach(int i in GetNumbers()
{
   Console.WriteLine(i);
}

private IEnumerable<int> GetNumbers()
{
   for(i = 0;i<100;i++) yield return i;
}
since yield only loads what is needed per iteration, you can break out of a loop without loading the entire collection.
Code:
private IEnumerable<int> GetNumbers()
{
   for(i = 0;i<100;i++) 
   if(1>50) break;
   yield return i;
}
the advantage here is that 51 to 99 would never be loaded into memory.

now numbers are trivial, but with rich domain objects this can be a great asset. here are some more links on the subject
Jason Meckley
Programmer
Specialty Bakers, Inc.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top