Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delegate interface implementation to other class in C#

Tags:

c#

interface

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?

like image 864
Willem Avatar asked Sep 24 '08 09:09

Willem


3 Answers

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.

like image 170
Jorge Ferreira Avatar answered Nov 15 '22 19:11

Jorge Ferreira


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.

like image 23
TcKs Avatar answered Nov 15 '22 19:11

TcKs


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

like image 23
Konrad Rudolph Avatar answered Nov 15 '22 19:11

Konrad Rudolph