C# 2.0 Iterators question

D

Dilip

Given a bunch of IEnumerable<T> objects, how do I iterate through them
and do a yield return on objects that satisfy one condition and
objects that satisfy another condition? I am still wrapping my head
over C# 2.0 iterators and I am not able to get this right.

public static IEnumerable<T> GetObjects(IEnumerable<T> objects)
{
foreach(T x in objects)
{
yield return x;
}
}

that obviously returns everything. I went the Predicate<T> route and
that got me here:

public static IEnumerable<T> GetObjects(IEnumerable<T> objects,
Predicate<T> condition)
{
foreach(T x in objects)
{
if (condition(x))
yield return x;
}
}

This works but it only returns objects that satisfy one condition.
What if I want all objects that return false too but on a different
call to GetObjects()?

Basically I am trying to find a way to use the same GetObjects()
function and vary the condition from the outside.

I can only work within the confines of .NET 2.0 (so no mindnumbing
LINQ suggestions :))

thanks!
 
J

Jon Skeet [C# MVP]

Dilip said:
Given a bunch of IEnumerable<T> objects, how do I iterate through them
and do a yield return on objects that satisfy one condition and
objects that satisfy another condition? I am still wrapping my head
over C# 2.0 iterators and I am not able to get this right.

public static IEnumerable<T> GetObjects(IEnumerable<T> objects)
{
foreach(T x in objects)
{
yield return x;
}
}

that obviously returns everything. I went the Predicate<T> route and
that got me here:

public static IEnumerable<T> GetObjects(IEnumerable<T> objects,
Predicate<T> condition)
{
foreach(T x in objects)
{
if (condition(x))
yield return x;
}
}

That seems to be right, yes.
This works but it only returns objects that satisfy one condition.
What if I want all objects that return false too but on a different
call to GetObjects()?

It's not at all clear what you mean here. You just call GetObjects()
with a different predicate, and it will be fine.
Basically I am trying to find a way to use the same GetObjects()
function and vary the condition from the outside.

You just pass in a different predicate - that's the point of the
predicate parameter in the first place.

Here's an example:

using System;
using System.Collections.Generic;

class Test
{
public static IEnumerable<T> GetObjects<T>(IEnumerable<T> objects,
Predicate<T> condition)
{
foreach(T x in objects)
{
if (condition(x))
yield return x;
}
}

static void Main()
{
Predicate<int> even = delegate(int x) { return x%2 == 0; };
Predicate<int> odd = delegate(int x) { return x%2 != 0; };

List<int> integers = new List<int>();
for (int i=0; i < 10; i++)
{
integers.Add(i);
}

Console.WriteLine("Even:");
foreach (int n in GetObjects(integers, even))
{
Console.WriteLine(n);
}

Console.WriteLine("Odd:");
foreach (int n in GetObjects(integers, odd))
{
Console.WriteLine(n);
}
}
}
 
P

Peter Duniho

[...]
public static IEnumerable<T> GetObjects(IEnumerable<T> objects,
Predicate<T> condition)
{
foreach(T x in objects)
{
if (condition(x))
yield return x;
}
}

This works but it only returns objects that satisfy one condition.
What if I want all objects that return false too but on a different
call to GetObjects()?

Basically I am trying to find a way to use the same GetObjects()
function and vary the condition from the outside.

I don't understand the question. What is passing the Predicate<T> to the
method not doing for you that you want it to? You can pass any arbitrary
method as that delegate, and you can do anything you want in that method.
Why does that version of your GetObjects() method not accomplish what you
want?

Can you give an example of some specific behavior you want, and which you
cannot figure out how to get?

Pete
 
D

Dilip

static void Main()
{
Predicate<int> even = delegate(int x) { return x%2 == 0; };
Predicate<int> odd = delegate(int x) { return x%2 != 0; };

List<int> integers = new List<int>();
for (int i=0; i < 10; i++)
{
integers.Add(i);
}

Console.WriteLine("Even:");
foreach (int n in GetObjects(integers, even))
{
Console.WriteLine(n);
}

Console.WriteLine("Odd:");
foreach (int n in GetObjects(integers, odd))
{
Console.WriteLine(n);
}
}

}

Jeez.. what a dumbass I am. In trying to think too hard about
something complicated I missed the obvious solution. Thanks Jon and
Peter for scratching your heads at my question. It made me tear my
hair out!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top