tags:

views:

1581

answers:

6

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?

A: 

Not unless you derive from List<T>.

public class MyEnum : List<SomeObject>, IEnumerable<SomeObject>{}
pb
Ok, this will work but I want to be sure that the calling code is incapable of type-casting the enumerator to List again and add or remove objects from it.
Willem
+1  A: 

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.

TcKs
The interface to implement is IEnumerable not IEnumerator.
smink
+1  A: 

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.

Sam
+3  A: 

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.

smink
+1  A: 

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!)

Konrad Rudolph
A: 

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.

Willem
You can pass by the `ReadOnlyCollection` because `IEnumerable`s are immutable anyway! The user'd have to upcast and guess the original type of the list in order to modify it. Copying the list is IMHO not a very good idea.
Konrad Rudolph