views:

47

answers:

1

I have a custom made collection that has many modes of objects generations inside of it.
It can generate everything, one object at a time or N objects at a time.
I would like to have the option to switch between implementations of generation on runtime, and even maybe create new ones.
I am looking for something with this kind of syntax:

foreach(var obj in myCollection.EnumerateAs(new LazyEnumerator())
{
   // ...
}

My problems are:
I don't know what does EnumerateAs() return? I am assuming that it's IEnumerator but will it still be the enumerator of my list?
Does LazyEnumerator inherit from IEnumerator?
How is it aware of myCollection?

+2  A: 

The return value of your EnumerateAs() should be IEnumerable<T>, where T is the type of object contained in your collection. I recommend reading more about yield return, as this may help you to understand how enumeration works. There is no default class for providing an enumeration 'strategy', but you can easily implement something like this by using yield return on the underlying collection in various ways.

It's not clear from your question exactly how the enumeration strategies would interact with your collection class. It looks like you might be after something like:

public interface IEnumerationStrategy<TCollection, T>
{
    IEnumerable<T> Enumerate(TCollection source);
}

public class Quark {}

public class MyCollection
{
    public IEnumerable<Quark> EnumerateAs(IEnumerationStrategy<MyCollection, Quark> strategy)
    {
        return strategy.Enumerate(this);
    }

    //Various special methods needed to implement stategies go here
}

public class SpecialStrategy: IEnumerationStrategy<MyCollection, Quark>
{
    public IEnumerable<Quark> Enumerate(MyCollection source)
    {
        //Use special methods to do custom enumeration via yield return that depends on specifics of MyCollection
    }
}

Note that you might also replace the strategy class with a simple strategy Func<MyCollection, IEnumerable<T>>, but the above matches your desired syntax most closely.

Dan Bryant
Could you show me a simple code example?How would EnumerateAs look like?Shouldn't the yield be in the LazyEnumerator itself?That means that I have to pass the list to the LazyEnumerator, right?
the_drow
So the enumeration strategy doesn't inherit from IEnumerator<T>?Thanks for the tip. I will create two overloads so it will also accept delegates :)
the_drow
This achieves the goal of your question, but my sense is that this may be more complex than you need. The strategies are tightly coupled to your custom MyCollection class, so there's little extensibility benefit and you might as well make the different enumerations methods of your collection. This would mainly be beneficial if you had a common interface for several special collections (it sounds like they're really more Generators than Collections) and wanted a way to share strategies across them via a standard interface.
Dan Bryant
I do have a common interface for all of my collections.If I was talking about one collection I wouldn't need the strategies as you said.I would have just made them member functions.However I need that extensibility since I have many collections that share the same interface and some have unique enumeration/generation combos.
the_drow
@the_drow, In that case, you might consider making the custom enumeration strategies extension methods of your common collection interface. This is more in line with the way LINQ works and will thus be more familiar to consumers of your code.
Dan Bryant
but here's the problem: some of my collections don't accept all enumeration strategies. so it sounds like a bad design to me.
the_drow