Как делегировать интерфейсную реализацию к другому классу в C#

8
задан Willem 24 September 2008 в 09:14
поделиться

6 ответов

Метод 1: Продолжите использовать инкапсуляцию и переводить вызовы к Реализации списка.

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();
    }
}

Метод 2: Наследуйтесь Реализации списка, Вы получаете то поведение бесплатно.

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();
    }
}

Метод 1 допускает лучшую игру в песочнице, поскольку нет никакого метода, который назовут в Списке без ведома MyEnum. Для наименьшего количества Метода усилия 2 предпочтен.

7
ответ дан 5 December 2019 в 22:21
поделиться

Можно сделать это:

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

Причина проста. Ваш класс может содержать несколько полей, которые являются наборами, таким образом, compiler/enviroment не может знать, какое поле должно использоваться для реализации "IEnumerator".

EIDT: Я соглашаюсь с @pb - Вы должны реализации интерфейс <SomeObject> IEnumerator.

1
ответ дан 5 December 2019 в 22:21
поделиться

Кроме использования метода свинца, это не возможно по “простой” причине: метод интерфейса должен быть передан a this указатель как первый аргумент. Когда Вы звоните GetEnumerator на Вашем объекте этот указатель будет Вашим объектом. Однако для вызова для работы над вложенным списком указатель должен был бы быть ссылкой на тот список, не классом.

Поэтому явно необходимо делегировать метод к другому объекту.

(И между прочим, совет в другом ответе был правильным: использовать IEnumerator<T>, нет IEnumerable!)

1
ответ дан 5 December 2019 в 22:21
поделиться

Если Вы хотите, возвращают набор способом, где вызывающая сторона не может изменить набор, Вы могли бы хотеть перенести Список в ReadOnlyCollection <> и возвратить IEnumerable <> ReadOnlyCollection <>.

Таким образом, можно быть уверены, что набор не будет изменен.

0
ответ дан 5 December 2019 в 22:21
поделиться

Не, если Вы не происходите из Списка <T>.

public class MyEnum : List<SomeObject>, IEnumerable<SomeObject>{}
-1
ответ дан 5 December 2019 в 22:21
поделиться

Спасибо всем за Ваш вход и объяснения. В конечном счете я объединил некоторые Ваши ответы на следующее:

    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();
    }
}

Это решение состоит в том, чтобы гарантировать, что код вызова неспособен к изменению списка, и каждый перечислитель независим от других каждым способом (например, с сортировкой). Еще раз спасибо.

-1
ответ дан 5 December 2019 в 22:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: