如何在C#中将接口实现委派给其他类

时间:2020-03-06 14:39:03  来源:igfitidea点击:

假设下面的类:

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

有必要在MyEnum中实现IEnumerator方法。
但是是否可以将IEnumerator的实现直接"委派"或者重定向到_myList而不需要实现IEnumerator方法?

解决方案

除非我们从List <T>派生。

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

你可以这样做:

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

原因很简单。类可以包含几个集合的字段,因此编译器/环境无法知道应使用哪个字段来实现" IEnumerator"。

EIDT:我同意@pb,我们应该实现IEnumerator <SomeObject>接口。

如果要以调用者无法修改集合的方式返回集合,则可能需要将列表包装到ReadOnlyCollection <>中并返回ReadOnlyCollection <>的IEnumerable <>。

这样,我们可以确保收藏集不会更改。

方法1:
继续使用封装并将调用转发到List实现。

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:
继承自List实现,我们可以免费获得该行为。

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知识的情况下,List中不会调用任何方法。最少省力,方法2是首选。

除了使用pb的方法外,由于简单的原因,这是不可能的:接口方法需要传递" this"指针作为第一个参数。当我们在对象上调用GetEnumerator时,该指针将成为对象。但是,为了使调用在嵌套列表上起作用,指针必须是对该列表的引用,而不是类。

因此,我们必须明确地将方法委托给另一个对象。

(顺便说一句,其他答复中的建议是正确的:使用IEnumerator &lt;T>,而不是IEnumerable!)

谢谢大家的投入和解释。
最终,我结合了我们对以下问题的一些答案:

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

该解决方案是确保调用代码无法修改列表,并且每个枚举器在每种方式上(例如排序)都独立于其他枚举器。
再次感谢。