Question

Assume the following class:

public class MyEnum: IEnumerator
{
    private List<SomeObject> _myList = new List<SomeObject>();
...
}

It is necessary to implement the IEnumerator methods in MyEnum. But is it possible to 'delegate' or redirect the implementation for IEnumerator directly to _myList without needing to implement the IEnumerator methods?

Was it helpful?

Solution

Method 1: Continue to use encapsulation and forward calls to the List implementation.

class SomeObject
{
}

class MyEnum : IEnumerable<SomeObject>
{
    private List<SomeObject> _myList = new List<SomeObject>();

    public void Add(SomeObject o)
    {
        _myList.Add(o);
    }

    public IEnumerator<SomeObject> GetEnumerator()
    {
        return _myList.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyEnum a = new MyEnum();
        a.Add(new SomeObject());

        foreach (SomeObject o in a)
        {
            Console.WriteLine(o.GetType().ToString());
        }

        Console.ReadLine();
    }
}

Method 2: Inherit from List implementation you get that behavior for free.

class SomeObject
{
}

class MyEnum : List<SomeObject>
{
}

class Program
{
    static void Main(string[] args)
    {
        MyEnum a = new MyEnum();
        a.Add(new SomeObject());

        foreach (SomeObject o in a)
        {
            Console.WriteLine(o.GetType().ToString());
        }

        Console.ReadLine();
    }
}

Method 1 allows for better sandboxing as there is no method that will be called in List without MyEnum knowledge. For least effort Method 2 is preferred.

OTHER TIPS

You can do this:

public class MyEnum : IEnumerator {
    private List<SomeObject> _myList = new List<SomeObject>();
    public IEnumerator GetEnumerator() { return this._myList.GetEnumerator(); }
}

The reason is simple. Your class can contains several fields which are collections, so compiler/enviroment can't know which field should be used for implementing "IEnumerator".

EIDT: I agree with @pb - you should implements IEnumerator<SomeObject> interface.

Apart from using pb's method, this isn't possible for a “simple” reason: the interface method needs to get passed a this pointer as the first argument. When you call GetEnumerator on your object, this pointer will be your object. However, in order for the invocation to work on the nested list, the pointer would have to be a reference to that list, not your class.

Therefore you explicitly have to delegate the method to the other object.

(And by the way, the advice in the other reply was right: use IEnumerator<T>, not IEnumerable!)

If you want return a collection in a way where the caller is unable to modify the collection, you might want to wrap the List into a ReadOnlyCollection<> and return IEnumerable<> of the ReadOnlyCollection<>.

This way you can be sure your collection will not be changed.

Not unless you derive from List<T>.

public class MyEnum : List<SomeObject>, IEnumerable<SomeObject>{}

Thank you all for your input and explanations. Eventually I have combined some of your answers to the following:

    class MyEnum : IEnumerable<SomeObject>
{
    private List<SomeObject> _myList = new List<SomeObject>();
    public IEnumerator<SomeObject> GetEnumerator()
    {
        // Create a read-only copy of the list.
        ReadOnlyCollection<CustomDevice> items = new ReadOnlyCollection<CustomDevice>(_myList);
        return items.GetEnumerator();
    }
}

This solution is to ensure the calling code is incapable of modifying the list and each enumerator is independant of the others in every way (e.g. with sorting). Thanks again.

Note that thanks to duck-typing, you can use foreach on any object that has a GetEnumerator method - the object type need not actually implement IEnumerable.

So if you do this:

class SomeObject
{
}

 class MyEnum
 {
    private List<SomeObject> _myList = new List<SomeObject>();

    public IEnumerator<SomeObject> GetEnumerator()
    {
        return _myList.GetEnumerator();
    }
 }

Then this works just fine:

MyEnum objects = new MyEnum();
// ... add some objects
foreach (SomeObject obj in objects)
{
    Console.WriteLine(obj.ToString());
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top